0
# Setup Tools Integration
1
2
Automatic generation of setuptools configuration from dependency analysis, bridging import tracking with package management by computing install_requires and extras_require.
3
4
## Capabilities
5
6
### Requirements Parsing
7
8
Parses requirements files or lists and generates setuptools-compatible install_requires and extras_require dictionaries based on actual module dependencies.
9
10
```python { .api }
11
def parse_requirements(
12
requirements: Union[List[str], str],
13
library_name: str,
14
extras_modules: Optional[List[str]] = None,
15
full_depth: bool = True,
16
keep_optional: Union[bool, Dict[str, List[str]]] = False,
17
**kwargs,
18
) -> Tuple[List[str], Dict[str, List[str]]]:
19
"""
20
Parse requirements and generate install_requires and extras_require for setuptools.
21
22
Uses dependency tracking to map each module within the project to its specific
23
dependencies, then allocates requirements between install_requires (common/required)
24
and extras_require (module-specific/optional).
25
26
Args:
27
requirements: The list of requirements entries, or a file path pointing to a
28
requirements file
29
library_name: The top-level name of the library package
30
extras_modules: List of module names that should be used to generate
31
extras_require sets
32
full_depth: Include transitive dependencies of direct third-party dependencies
33
keep_optional: Indicate which optional dependencies should be kept when computing
34
extras sets. If True, all optional dependencies are kept.
35
If False, none are kept. If dict, maps modules to lists of
36
optional dependencies to keep.
37
**kwargs: Additional keyword arguments to pass through to track_module
38
39
Returns:
40
requirements: The list of requirements to pass to setup()
41
extras_require: The extras_require dict to pass to setup()
42
"""
43
```
44
45
### Basic Setup Integration
46
47
Simple integration for generating setuptools configuration:
48
49
```python
50
import setuptools
51
from import_tracker.setup_tools import parse_requirements
52
53
# Parse requirements from file
54
install_requires, extras_require = parse_requirements(
55
requirements='requirements.txt',
56
library_name='my_package'
57
)
58
59
# Use in setup.py
60
setuptools.setup(
61
name='my_package',
62
version='1.0.0',
63
install_requires=install_requires,
64
extras_require=extras_require,
65
packages=setuptools.find_packages(),
66
)
67
```
68
69
### Requirements File Parsing
70
71
Parse dependencies from requirements.txt files:
72
73
```python
74
# requirements.txt content:
75
# requests>=2.25.0
76
# numpy>=1.20.0
77
# matplotlib>=3.0.0 # Optional for plotting
78
# seaborn>=0.11.0 # Optional for advanced plotting
79
80
install_requires, extras_require = parse_requirements(
81
requirements='requirements.txt',
82
library_name='my_package',
83
extras_modules=['my_package.plotting']
84
)
85
86
print(install_requires)
87
# ['requests>=2.25.0', 'numpy>=1.20.0']
88
89
print(extras_require)
90
# {
91
# 'my_package.plotting': ['matplotlib>=3.0.0', 'seaborn>=0.11.0'],
92
# 'all': ['matplotlib>=3.0.0', 'seaborn>=0.11.0']
93
# }
94
```
95
96
### In-Memory Requirements
97
98
Pass requirements as a list instead of a file:
99
100
```python
101
requirements_list = [
102
'requests>=2.25.0',
103
'numpy>=1.20.0',
104
'pandas>=1.3.0',
105
'matplotlib>=3.0.0'
106
]
107
108
install_requires, extras_require = parse_requirements(
109
requirements=requirements_list,
110
library_name='my_package',
111
extras_modules=[
112
'my_package.data_processing',
113
'my_package.visualization'
114
]
115
)
116
```
117
118
### Multiple Extras Groups
119
120
Generate multiple extras_require sets for different feature groups:
121
122
```python
123
install_requires, extras_require = parse_requirements(
124
requirements='requirements.txt',
125
library_name='my_package',
126
extras_modules=[
127
'my_package.web', # Web scraping features
128
'my_package.ml', # Machine learning features
129
'my_package.viz' # Visualization features
130
]
131
)
132
133
print(extras_require)
134
# {
135
# 'my_package.web': ['requests', 'beautifulsoup4'],
136
# 'my_package.ml': ['scikit-learn', 'tensorflow'],
137
# 'my_package.viz': ['matplotlib', 'plotly'],
138
# 'all': ['requests', 'beautifulsoup4', 'scikit-learn', 'tensorflow', 'matplotlib', 'plotly']
139
# }
140
```
141
142
### Optional Dependency Handling
143
144
Control which optional dependencies are included in extras:
145
146
```python
147
# Keep all optional dependencies
148
install_requires, extras_require = parse_requirements(
149
requirements='requirements.txt',
150
library_name='my_package',
151
extras_modules=['my_package.optional_features'],
152
keep_optional=True
153
)
154
155
# Keep no optional dependencies (only required ones)
156
install_requires, extras_require = parse_requirements(
157
requirements='requirements.txt',
158
library_name='my_package',
159
extras_modules=['my_package.optional_features'],
160
keep_optional=False
161
)
162
163
# Keep specific optional dependencies per module
164
install_requires, extras_require = parse_requirements(
165
requirements='requirements.txt',
166
library_name='my_package',
167
extras_modules=['my_package.optional_features'],
168
keep_optional={
169
'my_package.optional_features': ['matplotlib', 'seaborn']
170
}
171
)
172
```
173
174
### Advanced Configuration
175
176
Fine-tune dependency analysis behavior:
177
178
```python
179
install_requires, extras_require = parse_requirements(
180
requirements='requirements.txt',
181
library_name='my_package',
182
extras_modules=['my_package.advanced'],
183
full_depth=True, # Include transitive third-party deps
184
keep_optional=True, # Keep optional dependencies
185
# Pass additional track_module arguments
186
detect_transitive=True, # Distinguish direct vs transitive
187
show_optional=True # Track optional dependency status
188
)
189
```
190
191
## Complete Setup.py Example
192
193
Comprehensive setup.py using import_tracker for dependency management:
194
195
```python
196
"""A setuptools setup module for my_package"""
197
198
import os
199
import setuptools
200
from import_tracker.setup_tools import parse_requirements
201
202
# Read the README to provide the long description
203
base_dir = os.path.abspath(os.path.dirname(__file__))
204
with open(os.path.join(base_dir, "README.md"), "r") as handle:
205
long_description = handle.read()
206
207
# Determine requirements file path
208
requirements_file = os.path.join(base_dir, "requirements.txt")
209
210
# Parse requirement sets using import_tracker
211
install_requires, extras_require = parse_requirements(
212
requirements_file=requirements_file,
213
library_name="my_package",
214
extras_modules=[
215
"my_package.web_scraping",
216
"my_package.data_analysis",
217
"my_package.machine_learning",
218
"my_package.visualization"
219
],
220
full_depth=True,
221
keep_optional=True
222
)
223
224
# Perform the standard setup call
225
setuptools.setup(
226
name="my_package",
227
version="1.0.0",
228
author="Your Name",
229
author_email="your.email@example.com",
230
description="A package with managed dependencies",
231
long_description=long_description,
232
long_description_content_type="text/markdown",
233
url="https://github.com/yourusername/my_package",
234
license="MIT",
235
classifiers=[
236
"Development Status :: 4 - Beta",
237
"Intended Audience :: Developers",
238
"License :: OSI Approved :: MIT License",
239
"Programming Language :: Python :: 3",
240
"Programming Language :: Python :: 3.7",
241
"Programming Language :: Python :: 3.8",
242
"Programming Language :: Python :: 3.9",
243
"Programming Language :: Python :: 3.10",
244
"Programming Language :: Python :: 3.11",
245
],
246
keywords=["dependencies", "packaging", "imports"],
247
packages=setuptools.find_packages(),
248
python_requires=">=3.7",
249
install_requires=install_requires,
250
extras_require=extras_require,
251
entry_points={
252
"console_scripts": [
253
"my-package=my_package.cli:main",
254
],
255
},
256
)
257
```
258
259
## Integration with Lazy Import Errors
260
261
Combine setup tools integration with lazy import error handling:
262
263
```python
264
# In your package's __init__.py
265
from import_tracker import lazy_import_errors
266
from import_tracker.setup_tools import parse_requirements
267
268
# Function to get extras modules for error messages
269
def get_extras_modules():
270
"""Return the set of modules managed as extras"""
271
return {
272
'my_package.web_scraping',
273
'my_package.data_analysis',
274
'my_package.visualization'
275
}
276
277
# Enable lazy errors with extras integration
278
lazy_import_errors(get_extras_modules=get_extras_modules)
279
280
# Import all submodules - won't crash if dependencies missing
281
from . import web_scraping
282
from . import data_analysis
283
from . import visualization
284
```
285
286
When a user tries to use a feature with missing dependencies:
287
288
```python
289
import my_package
290
291
# This will show helpful installation message
292
my_package.visualization.plot_data()
293
# ModuleNotFoundError: No module named 'matplotlib'.
294
# To install the missing dependencies, run `pip install my_package[my_package.visualization]`
295
```
296
297
## Dependency Mapping
298
299
The system automatically maps Python import names to package names:
300
301
```python
302
# Import name -> Package name mapping examples
303
{
304
'requests': 'requests',
305
'numpy': 'numpy',
306
'pandas': 'pandas',
307
'matplotlib': 'matplotlib',
308
'PIL': 'pillow', # Special case mapping
309
'cv2': 'opencv-python', # Special case mapping
310
'sklearn': 'scikit-learn' # Special case mapping
311
}
312
```
313
314
## Return Values
315
316
### install_requires Format
317
318
List of requirement strings compatible with setuptools:
319
320
```python
321
[
322
'requests>=2.25.0',
323
'numpy>=1.20.0',
324
'click>=8.0.0'
325
]
326
```
327
328
### extras_require Format
329
330
Dictionary mapping extras names to requirement lists:
331
332
```python
333
{
334
'my_package.web': ['beautifulsoup4>=4.9.0', 'lxml>=4.6.0'],
335
'my_package.data': ['pandas>=1.3.0', 'openpyxl>=3.0.0'],
336
'my_package.viz': ['matplotlib>=3.4.0', 'seaborn>=0.11.0'],
337
'all': ['beautifulsoup4>=4.9.0', 'lxml>=4.6.0', 'pandas>=1.3.0',
338
'openpyxl>=3.0.0', 'matplotlib>=3.4.0', 'seaborn>=0.11.0']
339
}
340
```
341
342
## Types
343
344
```python { .api }
345
from typing import Dict, List, Optional, Tuple, Union
346
347
# Function parameter types
348
RequirementsInput = Union[List[str], str]
349
LibraryName = str
350
ExtrasModules = Optional[List[str]]
351
KeepOptional = Union[bool, Dict[str, List[str]]]
352
353
# Return types
354
InstallRequires = List[str]
355
ExtrasRequire = Dict[str, List[str]]
356
ParseRequirementsReturn = Tuple[InstallRequires, ExtrasRequire]
357
358
# Requirements mapping types
359
RequirementSpec = str # e.g., 'requests>=2.25.0'
360
PackageName = str # e.g., 'requests'
361
ModuleName = str # e.g., 'my_package.web'
362
```