syncable_cli/analyzer/frameworks/
python.rs

1use super::{FrameworkDetectionUtils, LanguageFrameworkDetector, TechnologyRule};
2use crate::analyzer::{DetectedLanguage, DetectedTechnology, LibraryType, TechnologyCategory};
3use crate::error::Result;
4
5pub struct PythonFrameworkDetector;
6
7impl LanguageFrameworkDetector for PythonFrameworkDetector {
8    fn detect_frameworks(&self, language: &DetectedLanguage) -> Result<Vec<DetectedTechnology>> {
9        let rules = get_python_technology_rules();
10
11        // Combine main and dev dependencies for comprehensive detection
12        let all_deps: Vec<String> = language
13            .main_dependencies
14            .iter()
15            .chain(language.dev_dependencies.iter())
16            .cloned()
17            .collect();
18
19        let technologies = FrameworkDetectionUtils::detect_technologies_by_dependencies(
20            &rules,
21            &all_deps,
22            language.confidence,
23        );
24
25        Ok(technologies)
26    }
27
28    fn supported_languages(&self) -> Vec<&'static str> {
29        vec!["Python"]
30    }
31}
32
33/// Python technology detection rules with comprehensive framework coverage
34fn get_python_technology_rules() -> Vec<TechnologyRule> {
35    vec![
36        // WEB FRAMEWORKS - Full Stack
37        TechnologyRule {
38            name: "Django".to_string(),
39            category: TechnologyCategory::BackendFramework,
40            confidence: 0.95,
41            dependency_patterns: vec!["django".to_string(), "Django".to_string()],
42            requires: vec![],
43            conflicts_with: vec![],
44            is_primary_indicator: true,
45            alternative_names: vec![],
46            file_indicators: vec![],
47        },
48        TechnologyRule {
49            name: "Django REST Framework".to_string(),
50            category: TechnologyCategory::BackendFramework,
51            confidence: 0.90,
52            dependency_patterns: vec![
53                "djangorestframework".to_string(),
54                "rest_framework".to_string(),
55            ],
56            requires: vec!["Django".to_string()],
57            conflicts_with: vec![],
58            is_primary_indicator: false,
59            alternative_names: vec!["DRF".to_string()],
60            file_indicators: vec![],
61        },
62        // MICRO FRAMEWORKS
63        TechnologyRule {
64            name: "Flask".to_string(),
65            category: TechnologyCategory::BackendFramework,
66            confidence: 0.95,
67            dependency_patterns: vec!["flask".to_string(), "Flask".to_string()],
68            requires: vec![],
69            conflicts_with: vec![],
70            is_primary_indicator: true,
71            alternative_names: vec![],
72            file_indicators: vec![],
73        },
74        TechnologyRule {
75            name: "FastAPI".to_string(),
76            category: TechnologyCategory::BackendFramework,
77            confidence: 0.95,
78            dependency_patterns: vec!["fastapi".to_string(), "FastAPI".to_string()],
79            requires: vec![],
80            conflicts_with: vec![],
81            is_primary_indicator: true,
82            alternative_names: vec![],
83            file_indicators: vec![],
84        },
85        TechnologyRule {
86            name: "Starlette".to_string(),
87            category: TechnologyCategory::BackendFramework,
88            confidence: 0.90,
89            dependency_patterns: vec!["starlette".to_string(), "Starlette".to_string()],
90            requires: vec![],
91            conflicts_with: vec![],
92            is_primary_indicator: true,
93            alternative_names: vec![],
94            file_indicators: vec![],
95        },
96        TechnologyRule {
97            name: "Quart".to_string(),
98            category: TechnologyCategory::BackendFramework,
99            confidence: 0.90,
100            dependency_patterns: vec!["quart".to_string(), "Quart".to_string()],
101            requires: vec![],
102            conflicts_with: vec![],
103            is_primary_indicator: true,
104            alternative_names: vec![],
105            file_indicators: vec![],
106        },
107        TechnologyRule {
108            name: "Sanic".to_string(),
109            category: TechnologyCategory::BackendFramework,
110            confidence: 0.90,
111            dependency_patterns: vec!["sanic".to_string(), "Sanic".to_string()],
112            requires: vec![],
113            conflicts_with: vec![],
114            is_primary_indicator: true,
115            alternative_names: vec![],
116            file_indicators: vec![],
117        },
118        TechnologyRule {
119            name: "Bottle".to_string(),
120            category: TechnologyCategory::BackendFramework,
121            confidence: 0.85,
122            dependency_patterns: vec!["bottle".to_string(), "Bottle".to_string()],
123            requires: vec![],
124            conflicts_with: vec![],
125            is_primary_indicator: true,
126            alternative_names: vec![],
127            file_indicators: vec![],
128        },
129        TechnologyRule {
130            name: "Falcon".to_string(),
131            category: TechnologyCategory::BackendFramework,
132            confidence: 0.85,
133            dependency_patterns: vec!["falcon".to_string(), "Falcon".to_string()],
134            requires: vec![],
135            conflicts_with: vec![],
136            is_primary_indicator: true,
137            alternative_names: vec![],
138            file_indicators: vec![],
139        },
140        TechnologyRule {
141            name: "Hug".to_string(),
142            category: TechnologyCategory::BackendFramework,
143            confidence: 0.85,
144            dependency_patterns: vec!["hug".to_string(), "Hug".to_string()],
145            requires: vec![],
146            conflicts_with: vec![],
147            is_primary_indicator: true,
148            alternative_names: vec![],
149            file_indicators: vec![],
150        },
151        TechnologyRule {
152            name: "Molten".to_string(),
153            category: TechnologyCategory::BackendFramework,
154            confidence: 0.85,
155            dependency_patterns: vec!["molten".to_string(), "Molten".to_string()],
156            requires: vec![],
157            conflicts_with: vec![],
158            is_primary_indicator: true,
159            alternative_names: vec![],
160            file_indicators: vec![],
161        },
162        TechnologyRule {
163            name: "Responder".to_string(),
164            category: TechnologyCategory::BackendFramework,
165            confidence: 0.85,
166            dependency_patterns: vec!["responder".to_string(), "Responder".to_string()],
167            requires: vec![],
168            conflicts_with: vec![],
169            is_primary_indicator: true,
170            alternative_names: vec![],
171            file_indicators: vec![],
172        },
173        TechnologyRule {
174            name: "Vibora".to_string(),
175            category: TechnologyCategory::BackendFramework,
176            confidence: 0.85,
177            dependency_patterns: vec!["vibora".to_string(), "Vibora".to_string()],
178            requires: vec![],
179            conflicts_with: vec![],
180            is_primary_indicator: true,
181            alternative_names: vec![],
182            file_indicators: vec![],
183        },
184        TechnologyRule {
185            name: "Asgi".to_string(),
186            category: TechnologyCategory::BackendFramework,
187            confidence: 0.85,
188            dependency_patterns: vec!["asgi".to_string(), "Asgi".to_string()],
189            requires: vec![],
190            conflicts_with: vec![],
191            is_primary_indicator: true,
192            alternative_names: vec![],
193            file_indicators: vec![],
194        },
195        TechnologyRule {
196            name: "Tornado".to_string(),
197            category: TechnologyCategory::BackendFramework,
198            confidence: 0.90,
199            dependency_patterns: vec!["tornado".to_string(), "Tornado".to_string()],
200            requires: vec![],
201            conflicts_with: vec![],
202            is_primary_indicator: true,
203            alternative_names: vec![],
204            file_indicators: vec![],
205        },
206        TechnologyRule {
207            name: "CherryPy".to_string(),
208            category: TechnologyCategory::BackendFramework,
209            confidence: 0.85,
210            dependency_patterns: vec!["cherrypy".to_string(), "CherryPy".to_string()],
211            requires: vec![],
212            conflicts_with: vec![],
213            is_primary_indicator: true,
214            alternative_names: vec![],
215            file_indicators: vec![],
216        },
217        TechnologyRule {
218            name: "Web2py".to_string(),
219            category: TechnologyCategory::BackendFramework,
220            confidence: 0.85,
221            dependency_patterns: vec!["web2py".to_string(), "Web2py".to_string()],
222            requires: vec![],
223            conflicts_with: vec![],
224            is_primary_indicator: true,
225            alternative_names: vec![],
226            file_indicators: vec![],
227        },
228        TechnologyRule {
229            name: "Pyramid".to_string(),
230            category: TechnologyCategory::BackendFramework,
231            confidence: 0.90,
232            dependency_patterns: vec!["pyramid".to_string(), "Pyramid".to_string()],
233            requires: vec![],
234            conflicts_with: vec![],
235            is_primary_indicator: true,
236            alternative_names: vec![],
237            file_indicators: vec![],
238        },
239        TechnologyRule {
240            name: "TurboGears".to_string(),
241            category: TechnologyCategory::BackendFramework,
242            confidence: 0.85,
243            dependency_patterns: vec!["tg".to_string(), "TurboGears".to_string()],
244            requires: vec![],
245            conflicts_with: vec![],
246            is_primary_indicator: true,
247            alternative_names: vec![],
248            file_indicators: vec![],
249        },
250        TechnologyRule {
251            name: "Klein".to_string(),
252            category: TechnologyCategory::BackendFramework,
253            confidence: 0.85,
254            dependency_patterns: vec!["klein".to_string(), "Klein".to_string()],
255            requires: vec![],
256            conflicts_with: vec![],
257            is_primary_indicator: true,
258            alternative_names: vec![],
259            file_indicators: vec![],
260        },
261        TechnologyRule {
262            name: "Morepath".to_string(),
263            category: TechnologyCategory::BackendFramework,
264            confidence: 0.85,
265            dependency_patterns: vec!["morepath".to_string(), "Morepath".to_string()],
266            requires: vec![],
267            conflicts_with: vec![],
268            is_primary_indicator: true,
269            alternative_names: vec![],
270            file_indicators: vec![],
271        },
272        TechnologyRule {
273            name: "Masonite".to_string(),
274            category: TechnologyCategory::BackendFramework,
275            confidence: 0.85,
276            dependency_patterns: vec!["masonite".to_string(), "Masonite".to_string()],
277            requires: vec![],
278            conflicts_with: vec![],
279            is_primary_indicator: true,
280            alternative_names: vec![],
281            file_indicators: vec![],
282        },
283        TechnologyRule {
284            name: "Litestar".to_string(),
285            category: TechnologyCategory::BackendFramework,
286            confidence: 0.90,
287            dependency_patterns: vec!["litestar".to_string(), "Litestar".to_string()],
288            requires: vec![],
289            conflicts_with: vec![],
290            is_primary_indicator: true,
291            alternative_names: vec!["Starlite".to_string()],
292            file_indicators: vec![],
293        },
294        TechnologyRule {
295            name: "Connexion".to_string(),
296            category: TechnologyCategory::BackendFramework,
297            confidence: 0.85,
298            dependency_patterns: vec!["connexion".to_string(), "Connexion".to_string()],
299            requires: vec![],
300            conflicts_with: vec![],
301            is_primary_indicator: true,
302            alternative_names: vec![],
303            file_indicators: vec![],
304        },
305        TechnologyRule {
306            name: "Nameko".to_string(),
307            category: TechnologyCategory::BackendFramework,
308            confidence: 0.85,
309            dependency_patterns: vec!["nameko".to_string(), "Nameko".to_string()],
310            requires: vec![],
311            conflicts_with: vec![],
312            is_primary_indicator: true,
313            alternative_names: vec![],
314            file_indicators: vec![],
315        },
316        TechnologyRule {
317            name: "Aiohttp".to_string(),
318            category: TechnologyCategory::BackendFramework,
319            confidence: 0.90,
320            dependency_patterns: vec!["aiohttp".to_string(), "Aiohttp".to_string()],
321            requires: vec![],
322            conflicts_with: vec![],
323            is_primary_indicator: true,
324            alternative_names: vec![],
325            file_indicators: vec![],
326        },
327        // ASYNC RUNTIMES
328        TechnologyRule {
329            name: "asyncio".to_string(),
330            category: TechnologyCategory::Runtime,
331            confidence: 0.85,
332            dependency_patterns: vec!["asyncio".to_string()],
333            requires: vec![],
334            conflicts_with: vec![],
335            is_primary_indicator: false,
336            alternative_names: vec![],
337            file_indicators: vec![],
338        },
339        TechnologyRule {
340            name: "Trio".to_string(),
341            category: TechnologyCategory::Runtime,
342            confidence: 0.85,
343            dependency_patterns: vec!["trio".to_string()],
344            requires: vec![],
345            conflicts_with: vec![],
346            is_primary_indicator: false,
347            alternative_names: vec![],
348            file_indicators: vec![],
349        },
350        TechnologyRule {
351            name: "Curio".to_string(),
352            category: TechnologyCategory::Runtime,
353            confidence: 0.85,
354            dependency_patterns: vec!["curio".to_string()],
355            requires: vec![],
356            conflicts_with: vec![],
357            is_primary_indicator: false,
358            alternative_names: vec![],
359            file_indicators: vec![],
360        },
361        // FRONTEND FRAMEWORKS
362        TechnologyRule {
363            name: "Streamlit".to_string(),
364            category: TechnologyCategory::FrontendFramework,
365            confidence: 0.95,
366            dependency_patterns: vec!["streamlit".to_string(), "Streamlit".to_string()],
367            requires: vec![],
368            conflicts_with: vec![],
369            is_primary_indicator: true,
370            alternative_names: vec![],
371            file_indicators: vec![],
372        },
373        TechnologyRule {
374            name: "Gradio".to_string(),
375            category: TechnologyCategory::FrontendFramework,
376            confidence: 0.95,
377            dependency_patterns: vec!["gradio".to_string(), "Gradio".to_string()],
378            requires: vec![],
379            conflicts_with: vec![],
380            is_primary_indicator: true,
381            alternative_names: vec![],
382            file_indicators: vec![],
383        },
384        TechnologyRule {
385            name: "Dash".to_string(),
386            category: TechnologyCategory::FrontendFramework,
387            confidence: 0.90,
388            dependency_patterns: vec!["dash".to_string(), "Dash".to_string()],
389            requires: vec!["Flask".to_string()],
390            conflicts_with: vec![],
391            is_primary_indicator: true,
392            alternative_names: vec![],
393            file_indicators: vec![],
394        },
395        TechnologyRule {
396            name: "Panel".to_string(),
397            category: TechnologyCategory::FrontendFramework,
398            confidence: 0.90,
399            dependency_patterns: vec!["panel".to_string(), "Panel".to_string()],
400            requires: vec!["Bokeh".to_string()],
401            conflicts_with: vec![],
402            is_primary_indicator: true,
403            alternative_names: vec![],
404            file_indicators: vec![],
405        },
406        TechnologyRule {
407            name: "NiceGUI".to_string(),
408            category: TechnologyCategory::FrontendFramework,
409            confidence: 0.90,
410            dependency_patterns: vec!["nicegui".to_string(), "NiceGUI".to_string()],
411            requires: vec![],
412            conflicts_with: vec![],
413            is_primary_indicator: true,
414            alternative_names: vec![],
415            file_indicators: vec![],
416        },
417        TechnologyRule {
418            name: "Reflex".to_string(),
419            category: TechnologyCategory::FrontendFramework,
420            confidence: 0.90,
421            dependency_patterns: vec!["reflex".to_string(), "Reflex".to_string()],
422            requires: vec![],
423            conflicts_with: vec![],
424            is_primary_indicator: true,
425            alternative_names: vec!["pynecone".to_string()],
426            file_indicators: vec![],
427        },
428        TechnologyRule {
429            name: "PyWebIO".to_string(),
430            category: TechnologyCategory::FrontendFramework,
431            confidence: 0.85,
432            dependency_patterns: vec!["pywebio".to_string(), "PyWebIO".to_string()],
433            requires: vec![],
434            conflicts_with: vec![],
435            is_primary_indicator: true,
436            alternative_names: vec![],
437            file_indicators: vec![],
438        },
439        TechnologyRule {
440            name: "Anvil".to_string(),
441            category: TechnologyCategory::FrontendFramework,
442            confidence: 0.85,
443            dependency_patterns: vec!["anvil".to_string(), "Anvil".to_string()],
444            requires: vec![],
445            conflicts_with: vec![],
446            is_primary_indicator: true,
447            alternative_names: vec![],
448            file_indicators: vec![],
449        },
450        // SCIENTIFIC COMPUTING
451        TechnologyRule {
452            name: "NumPy".to_string(),
453            category: TechnologyCategory::Library(LibraryType::Utility),
454            confidence: 0.90,
455            dependency_patterns: vec!["numpy".to_string(), "NumPy".to_string()],
456            requires: vec![],
457            conflicts_with: vec![],
458            is_primary_indicator: false,
459            alternative_names: vec![],
460            file_indicators: vec![],
461        },
462        TechnologyRule {
463            name: "SciPy".to_string(),
464            category: TechnologyCategory::Library(LibraryType::Utility),
465            confidence: 0.90,
466            dependency_patterns: vec!["scipy".to_string(), "SciPy".to_string()],
467            requires: vec!["NumPy".to_string()],
468            conflicts_with: vec![],
469            is_primary_indicator: false,
470            alternative_names: vec![],
471            file_indicators: vec![],
472        },
473        TechnologyRule {
474            name: "Pandas".to_string(),
475            category: TechnologyCategory::Library(LibraryType::Utility),
476            confidence: 0.90,
477            dependency_patterns: vec!["pandas".to_string(), "Pandas".to_string()],
478            requires: vec!["NumPy".to_string()],
479            conflicts_with: vec![],
480            is_primary_indicator: false,
481            alternative_names: vec![],
482            file_indicators: vec![],
483        },
484        TechnologyRule {
485            name: "Matplotlib".to_string(),
486            category: TechnologyCategory::Library(LibraryType::Utility),
487            confidence: 0.85,
488            dependency_patterns: vec!["matplotlib".to_string(), "Matplotlib".to_string()],
489            requires: vec![],
490            conflicts_with: vec![],
491            is_primary_indicator: false,
492            alternative_names: vec![],
493            file_indicators: vec![],
494        },
495        TechnologyRule {
496            name: "Seaborn".to_string(),
497            category: TechnologyCategory::Library(LibraryType::Utility),
498            confidence: 0.85,
499            dependency_patterns: vec!["seaborn".to_string(), "Seaborn".to_string()],
500            requires: vec!["Matplotlib".to_string(), "Pandas".to_string()],
501            conflicts_with: vec![],
502            is_primary_indicator: false,
503            alternative_names: vec![],
504            file_indicators: vec![],
505        },
506        TechnologyRule {
507            name: "Plotly".to_string(),
508            category: TechnologyCategory::Library(LibraryType::Utility),
509            confidence: 0.85,
510            dependency_patterns: vec!["plotly".to_string(), "Plotly".to_string()],
511            requires: vec![],
512            conflicts_with: vec![],
513            is_primary_indicator: false,
514            alternative_names: vec![],
515            file_indicators: vec![],
516        },
517        TechnologyRule {
518            name: "Bokeh".to_string(),
519            category: TechnologyCategory::Library(LibraryType::Utility),
520            confidence: 0.85,
521            dependency_patterns: vec!["bokeh".to_string(), "Bokeh".to_string()],
522            requires: vec![],
523            conflicts_with: vec![],
524            is_primary_indicator: false,
525            alternative_names: vec![],
526            file_indicators: vec![],
527        },
528        // MACHINE LEARNING & AI
529        TechnologyRule {
530            name: "TensorFlow".to_string(),
531            category: TechnologyCategory::Library(LibraryType::Utility),
532            confidence: 0.95,
533            dependency_patterns: vec!["tensorflow".to_string(), "TensorFlow".to_string()],
534            requires: vec![],
535            conflicts_with: vec![],
536            is_primary_indicator: false,
537            alternative_names: vec![],
538            file_indicators: vec![],
539        },
540        TechnologyRule {
541            name: "PyTorch".to_string(),
542            category: TechnologyCategory::Library(LibraryType::Utility),
543            confidence: 0.95,
544            dependency_patterns: vec!["torch".to_string(), "PyTorch".to_string()],
545            requires: vec![],
546            conflicts_with: vec![],
547            is_primary_indicator: false,
548            alternative_names: vec![],
549            file_indicators: vec![],
550        },
551        TechnologyRule {
552            name: "Scikit-learn".to_string(),
553            category: TechnologyCategory::Library(LibraryType::Utility),
554            confidence: 0.90,
555            dependency_patterns: vec!["scikit-learn".to_string(), "sklearn".to_string()],
556            requires: vec!["NumPy".to_string(), "SciPy".to_string()],
557            conflicts_with: vec![],
558            is_primary_indicator: false,
559            alternative_names: vec!["sklearn".to_string()],
560            file_indicators: vec![],
561        },
562        TechnologyRule {
563            name: "Keras".to_string(),
564            category: TechnologyCategory::Library(LibraryType::Utility),
565            confidence: 0.90,
566            dependency_patterns: vec!["keras".to_string(), "Keras".to_string()],
567            requires: vec!["TensorFlow".to_string()],
568            conflicts_with: vec![],
569            is_primary_indicator: false,
570            alternative_names: vec![],
571            file_indicators: vec![],
572        },
573        TechnologyRule {
574            name: "XGBoost".to_string(),
575            category: TechnologyCategory::Library(LibraryType::Utility),
576            confidence: 0.85,
577            dependency_patterns: vec!["xgboost".to_string(), "XGBoost".to_string()],
578            requires: vec![],
579            conflicts_with: vec![],
580            is_primary_indicator: false,
581            alternative_names: vec![],
582            file_indicators: vec![],
583        },
584        TechnologyRule {
585            name: "LightGBM".to_string(),
586            category: TechnologyCategory::Library(LibraryType::Utility),
587            confidence: 0.85,
588            dependency_patterns: vec!["lightgbm".to_string(), "LightGBM".to_string()],
589            requires: vec![],
590            conflicts_with: vec![],
591            is_primary_indicator: false,
592            alternative_names: vec![],
593            file_indicators: vec![],
594        },
595        TechnologyRule {
596            name: "CatBoost".to_string(),
597            category: TechnologyCategory::Library(LibraryType::Utility),
598            confidence: 0.85,
599            dependency_patterns: vec!["catboost".to_string(), "CatBoost".to_string()],
600            requires: vec![],
601            conflicts_with: vec![],
602            is_primary_indicator: false,
603            alternative_names: vec![],
604            file_indicators: vec![],
605        },
606        // DATABASE/ORM
607        TechnologyRule {
608            name: "SQLAlchemy".to_string(),
609            category: TechnologyCategory::Database,
610            confidence: 0.90,
611            dependency_patterns: vec!["sqlalchemy".to_string(), "SQLAlchemy".to_string()],
612            requires: vec![],
613            conflicts_with: vec![],
614            is_primary_indicator: false,
615            alternative_names: vec![],
616            file_indicators: vec![],
617        },
618        TechnologyRule {
619            name: "Peewee".to_string(),
620            category: TechnologyCategory::Database,
621            confidence: 0.85,
622            dependency_patterns: vec!["peewee".to_string(), "Peewee".to_string()],
623            requires: vec![],
624            conflicts_with: vec![],
625            is_primary_indicator: false,
626            alternative_names: vec![],
627            file_indicators: vec![],
628        },
629        TechnologyRule {
630            name: "Tortoise ORM".to_string(),
631            category: TechnologyCategory::Database,
632            confidence: 0.85,
633            dependency_patterns: vec!["tortoise-orm".to_string(), "tortoise".to_string()],
634            requires: vec![],
635            conflicts_with: vec![],
636            is_primary_indicator: false,
637            alternative_names: vec!["tortoise".to_string()],
638            file_indicators: vec![],
639        },
640        TechnologyRule {
641            name: "Django ORM".to_string(),
642            category: TechnologyCategory::Database,
643            confidence: 0.90,
644            dependency_patterns: vec!["django".to_string()],
645            requires: vec!["Django".to_string()],
646            conflicts_with: vec![],
647            is_primary_indicator: false,
648            alternative_names: vec![],
649            file_indicators: vec![],
650        },
651        TechnologyRule {
652            name: "MongoEngine".to_string(),
653            category: TechnologyCategory::Database,
654            confidence: 0.85,
655            dependency_patterns: vec!["mongoengine".to_string(), "MongoEngine".to_string()],
656            requires: vec![],
657            conflicts_with: vec![],
658            is_primary_indicator: false,
659            alternative_names: vec![],
660            file_indicators: vec![],
661        },
662        TechnologyRule {
663            name: "Pymongo".to_string(),
664            category: TechnologyCategory::Database,
665            confidence: 0.85,
666            dependency_patterns: vec!["pymongo".to_string(), "Pymongo".to_string()],
667            requires: vec![],
668            conflicts_with: vec![],
669            is_primary_indicator: false,
670            alternative_names: vec![],
671            file_indicators: vec![],
672        },
673        // TESTING
674        TechnologyRule {
675            name: "Pytest".to_string(),
676            category: TechnologyCategory::Testing,
677            confidence: 0.90,
678            dependency_patterns: vec!["pytest".to_string(), "Pytest".to_string()],
679            requires: vec![],
680            conflicts_with: vec![],
681            is_primary_indicator: false,
682            alternative_names: vec![],
683            file_indicators: vec![],
684        },
685        TechnologyRule {
686            name: "Unittest".to_string(),
687            category: TechnologyCategory::Testing,
688            confidence: 0.80,
689            dependency_patterns: vec!["unittest".to_string()],
690            requires: vec![],
691            conflicts_with: vec![],
692            is_primary_indicator: false,
693            alternative_names: vec![],
694            file_indicators: vec![],
695        },
696        TechnologyRule {
697            name: "Tox".to_string(),
698            category: TechnologyCategory::Testing,
699            confidence: 0.80,
700            dependency_patterns: vec!["tox".to_string()],
701            requires: vec![],
702            conflicts_with: vec![],
703            is_primary_indicator: false,
704            alternative_names: vec![],
705            file_indicators: vec![],
706        },
707        TechnologyRule {
708            name: "Nose".to_string(),
709            category: TechnologyCategory::Testing,
710            confidence: 0.75,
711            dependency_patterns: vec!["nose".to_string(), "nose2".to_string()],
712            requires: vec![],
713            conflicts_with: vec![],
714            is_primary_indicator: false,
715            alternative_names: vec!["nose2".to_string()],
716            file_indicators: vec![],
717        },
718        TechnologyRule {
719            name: "Behave".to_string(),
720            category: TechnologyCategory::Testing,
721            confidence: 0.85,
722            dependency_patterns: vec!["behave".to_string()],
723            requires: vec![],
724            conflicts_with: vec![],
725            is_primary_indicator: false,
726            alternative_names: vec![],
727            file_indicators: vec![],
728        },
729        TechnologyRule {
730            name: "Hypothesis".to_string(),
731            category: TechnologyCategory::Testing,
732            confidence: 0.85,
733            dependency_patterns: vec!["hypothesis".to_string()],
734            requires: vec![],
735            conflicts_with: vec![],
736            is_primary_indicator: false,
737            alternative_names: vec![],
738            file_indicators: vec![],
739        },
740        // CLI FRAMEWORKS
741        TechnologyRule {
742            name: "Click".to_string(),
743            category: TechnologyCategory::Library(LibraryType::CLI),
744            confidence: 0.90,
745            dependency_patterns: vec!["click".to_string(), "Click".to_string()],
746            requires: vec![],
747            conflicts_with: vec![],
748            is_primary_indicator: true,
749            alternative_names: vec![],
750            file_indicators: vec![],
751        },
752        TechnologyRule {
753            name: "Argparse".to_string(),
754            category: TechnologyCategory::Library(LibraryType::CLI),
755            confidence: 0.80,
756            dependency_patterns: vec!["argparse".to_string()],
757            requires: vec![],
758            conflicts_with: vec![],
759            is_primary_indicator: true,
760            alternative_names: vec![],
761            file_indicators: vec![],
762        },
763        TechnologyRule {
764            name: "Fire".to_string(),
765            category: TechnologyCategory::Library(LibraryType::CLI),
766            confidence: 0.85,
767            dependency_patterns: vec!["fire".to_string(), "Fire".to_string()],
768            requires: vec![],
769            conflicts_with: vec![],
770            is_primary_indicator: true,
771            alternative_names: vec![],
772            file_indicators: vec![],
773        },
774        TechnologyRule {
775            name: "Typer".to_string(),
776            category: TechnologyCategory::Library(LibraryType::CLI),
777            confidence: 0.85,
778            dependency_patterns: vec!["typer".to_string(), "Typer".to_string()],
779            requires: vec!["Click".to_string()],
780            conflicts_with: vec![],
781            is_primary_indicator: true,
782            alternative_names: vec![],
783            file_indicators: vec![],
784        },
785        TechnologyRule {
786            name: "Docopt".to_string(),
787            category: TechnologyCategory::Library(LibraryType::CLI),
788            confidence: 0.80,
789            dependency_patterns: vec!["docopt".to_string(), "Docopt".to_string()],
790            requires: vec![],
791            conflicts_with: vec![],
792            is_primary_indicator: true,
793            alternative_names: vec![],
794            file_indicators: vec![],
795        },
796        TechnologyRule {
797            name: "Plac".to_string(),
798            category: TechnologyCategory::Library(LibraryType::CLI),
799            confidence: 0.80,
800            dependency_patterns: vec!["plac".to_string(), "Plac".to_string()],
801            requires: vec![],
802            conflicts_with: vec![],
803            is_primary_indicator: true,
804            alternative_names: vec![],
805            file_indicators: vec![],
806        },
807        // ASYNC TASK QUEUES
808        TechnologyRule {
809            name: "Celery".to_string(),
810            category: TechnologyCategory::Library(LibraryType::Utility),
811            confidence: 0.90,
812            dependency_patterns: vec!["celery".to_string(), "Celery".to_string()],
813            requires: vec![],
814            conflicts_with: vec![],
815            is_primary_indicator: false,
816            alternative_names: vec![],
817            file_indicators: vec![],
818        },
819        TechnologyRule {
820            name: "RQ".to_string(),
821            category: TechnologyCategory::Library(LibraryType::Utility),
822            confidence: 0.85,
823            dependency_patterns: vec!["rq".to_string(), "RQ".to_string()],
824            requires: vec![],
825            conflicts_with: vec![],
826            is_primary_indicator: false,
827            alternative_names: vec![],
828            file_indicators: vec![],
829        },
830        TechnologyRule {
831            name: "Dramatiq".to_string(),
832            category: TechnologyCategory::Library(LibraryType::Utility),
833            confidence: 0.85,
834            dependency_patterns: vec!["dramatiq".to_string(), "Dramatiq".to_string()],
835            requires: vec![],
836            conflicts_with: vec![],
837            is_primary_indicator: false,
838            alternative_names: vec![],
839            file_indicators: vec![],
840        },
841        TechnologyRule {
842            name: "Huey".to_string(),
843            category: TechnologyCategory::Library(LibraryType::Utility),
844            confidence: 0.85,
845            dependency_patterns: vec!["huey".to_string(), "Huey".to_string()],
846            requires: vec![],
847            conflicts_with: vec![],
848            is_primary_indicator: false,
849            alternative_names: vec![],
850            file_indicators: vec![],
851        },
852        // CONFIGURATION
853        TechnologyRule {
854            name: "Pydantic".to_string(),
855            category: TechnologyCategory::Library(LibraryType::Utility),
856            confidence: 0.90,
857            dependency_patterns: vec!["pydantic".to_string(), "Pydantic".to_string()],
858            requires: vec![],
859            conflicts_with: vec![],
860            is_primary_indicator: false,
861            alternative_names: vec![],
862            file_indicators: vec![],
863        },
864        TechnologyRule {
865            name: "ConfigParser".to_string(),
866            category: TechnologyCategory::Library(LibraryType::Utility),
867            confidence: 0.80,
868            dependency_patterns: vec!["configparser".to_string()],
869            requires: vec![],
870            conflicts_with: vec![],
871            is_primary_indicator: false,
872            alternative_names: vec![],
873            file_indicators: vec![],
874        },
875        TechnologyRule {
876            name: "PyYAML".to_string(),
877            category: TechnologyCategory::Library(LibraryType::Utility),
878            confidence: 0.85,
879            dependency_patterns: vec!["pyyaml".to_string(), "PyYAML".to_string()],
880            requires: vec![],
881            conflicts_with: vec![],
882            is_primary_indicator: false,
883            alternative_names: vec!["yaml".to_string()],
884            file_indicators: vec![],
885        },
886        TechnologyRule {
887            name: "Toml".to_string(),
888            category: TechnologyCategory::Library(LibraryType::Utility),
889            confidence: 0.85,
890            dependency_patterns: vec!["toml".to_string(), "Toml".to_string()],
891            requires: vec![],
892            conflicts_with: vec![],
893            is_primary_indicator: false,
894            alternative_names: vec![],
895            file_indicators: vec![],
896        },
897        // HTTP CLIENTS
898        TechnologyRule {
899            name: "Requests".to_string(),
900            category: TechnologyCategory::Library(LibraryType::HttpClient),
901            confidence: 0.90,
902            dependency_patterns: vec!["requests".to_string(), "Requests".to_string()],
903            requires: vec![],
904            conflicts_with: vec![],
905            is_primary_indicator: false,
906            alternative_names: vec![],
907            file_indicators: vec![],
908        },
909        TechnologyRule {
910            name: "Httpx".to_string(),
911            category: TechnologyCategory::Library(LibraryType::HttpClient),
912            confidence: 0.85,
913            dependency_patterns: vec!["httpx".to_string(), "Httpx".to_string()],
914            requires: vec![],
915            conflicts_with: vec![],
916            is_primary_indicator: false,
917            alternative_names: vec![],
918            file_indicators: vec![],
919        },
920        TechnologyRule {
921            name: "Aiohttp Client".to_string(),
922            category: TechnologyCategory::Library(LibraryType::HttpClient),
923            confidence: 0.85,
924            dependency_patterns: vec!["aiohttp".to_string()],
925            requires: vec![],
926            conflicts_with: vec![],
927            is_primary_indicator: false,
928            alternative_names: vec![],
929            file_indicators: vec![],
930        },
931        TechnologyRule {
932            name: "Urllib3".to_string(),
933            category: TechnologyCategory::Library(LibraryType::HttpClient),
934            confidence: 0.80,
935            dependency_patterns: vec!["urllib3".to_string(), "Urllib3".to_string()],
936            requires: vec![],
937            conflicts_with: vec![],
938            is_primary_indicator: false,
939            alternative_names: vec![],
940            file_indicators: vec![],
941        },
942    ]
943}