25
25
apply_default_predicate ,
26
26
)
27
27
from sphinx_needs .logging import get_logger , log_warning
28
- from sphinx_needs .need_item import NeedItem
28
+ from sphinx_needs .need_item import (
29
+ NeedItem ,
30
+ NeedItemSourceProtocol ,
31
+ NeedItemSourceUnknown ,
32
+ )
29
33
from sphinx_needs .nodes import Need
30
34
from sphinx_needs .roles .need_part import find_parts , update_need_with_parts
31
35
from sphinx_needs .utils import jinja_parse
@@ -47,6 +51,7 @@ def generate_need(
47
51
need_type : str ,
48
52
title : str ,
49
53
* ,
54
+ need_source : NeedItemSourceProtocol | None = None ,
50
55
docname : None | str = None ,
51
56
lineno : None | int = None ,
52
57
id : str | None = None ,
@@ -128,8 +133,25 @@ def generate_need(
128
133
:param pre_template: Template name to use for content added before need
129
134
:param post_template: Template name to use for the content added after need
130
135
"""
136
+ source = (
137
+ NeedItemSourceUnknown (
138
+ docname = docname ,
139
+ lineno = lineno ,
140
+ lineno_content = lineno_content ,
141
+ is_import = is_import ,
142
+ is_external = is_external ,
143
+ external_url = external_url if is_external else None ,
144
+ )
145
+ if need_source is None
146
+ else need_source
147
+ )
148
+
131
149
# location is used to provide source mapped warnings
132
- location = (docname , lineno ) if docname else None
150
+ location = (
151
+ (source .dict_repr ["docname" ], source .dict_repr ["lineno" ])
152
+ if source .dict_repr ["docname" ]
153
+ else None
154
+ )
133
155
134
156
# validate kwargs
135
157
allowed_kwargs = {x ["option" ] for x in needs_config .extra_links } | set (
@@ -230,9 +252,9 @@ def generate_need(
230
252
"title" : title ,
231
253
"tags" : tuple (tags or []),
232
254
"status" : status ,
233
- "docname" : docname ,
234
- "is_import" : is_import ,
235
- "is_external" : is_external ,
255
+ "docname" : source . dict_repr [ " docname" ] ,
256
+ "is_import" : source . dict_repr [ " is_import" ] ,
257
+ "is_external" : source . dict_repr [ " is_external" ] ,
236
258
}
237
259
defaults_extras = extras_no_defaults .copy ()
238
260
defaults_links = {k : tuple (v or []) for k , v in links_no_defaults .items ()}
@@ -306,9 +328,6 @@ def generate_need(
306
328
307
329
# Add the need and all needed information
308
330
needs_data : NeedsInfoType = {
309
- "docname" : docname ,
310
- "lineno" : lineno ,
311
- "lineno_content" : lineno_content ,
312
331
"doctype" : doctype ,
313
332
"content" : content ,
314
333
"pre_content" : None ,
@@ -340,9 +359,6 @@ def generate_need(
340
359
"is_need" : True ,
341
360
"id_parent" : need_id ,
342
361
"id_complete" : need_id ,
343
- "is_import" : is_import ,
344
- "is_external" : is_external ,
345
- "external_url" : external_url if is_external else None ,
346
362
"external_css" : external_css or "external_link" ,
347
363
"is_modified" : False ,
348
364
"modifications" : 0 ,
@@ -354,7 +370,9 @@ def generate_need(
354
370
"parent_need" : parent_need ,
355
371
}
356
372
357
- needs_info = NeedItem (core = needs_data , extras = extras , links = links , _validate = False )
373
+ needs_info = NeedItem (
374
+ core = needs_data , extras = extras , links = links , source = source , _validate = False
375
+ )
358
376
359
377
if jinja_content :
360
378
need_content_context : dict [str , Any ] = {** needs_info }
@@ -390,12 +408,13 @@ def generate_need(
390
408
391
409
def add_need (
392
410
app : Sphinx ,
393
- state : None | RSTState ,
394
- docname : None | str ,
395
- lineno : None | int ,
396
- need_type : str ,
397
- title : str ,
411
+ state : None | RSTState = None ,
412
+ docname : None | str = None ,
413
+ lineno : None | int = None ,
414
+ need_type : str = "" ,
415
+ title : str = "" ,
398
416
* ,
417
+ need_source : NeedItemSourceProtocol | None = None ,
399
418
id : str | None = None ,
400
419
content : str | StringList = "" ,
401
420
lineno_content : None | int = None ,
@@ -485,11 +504,16 @@ def add_need(
485
504
)
486
505
kwargs = {k : v for k , v in kwargs .items () if k not in _deprecated_kwargs }
487
506
488
- if doctype is None and not is_external and docname :
489
- doctype = os .path .splitext (app .env .doc2path (docname ))[1 ]
507
+ if (
508
+ doctype is None
509
+ and not (need_source .dict_repr ["is_external" ] if need_source else is_external )
510
+ and (_docname := need_source .dict_repr ["docname" ] if need_source else docname )
511
+ ):
512
+ doctype = os .path .splitext (app .env .doc2path (_docname ))[1 ]
490
513
491
514
needs_info = generate_need (
492
515
needs_config = NeedsSphinxConfig (app .config ),
516
+ need_source = need_source ,
493
517
need_type = need_type ,
494
518
title = title ,
495
519
full_title = full_title ,
@@ -697,6 +721,7 @@ def add_external_need(
697
721
need_type : str ,
698
722
title : str | None = None ,
699
723
id : str | None = None ,
724
+ need_source : NeedItemSourceProtocol | None = None ,
700
725
external_url : str | None = None ,
701
726
external_css : str = "external_link" ,
702
727
content : str = "" ,
@@ -738,9 +763,7 @@ def add_external_need(
738
763
739
764
return add_need (
740
765
app = app ,
741
- state = None ,
742
- docname = None ,
743
- lineno = None ,
766
+ need_source = need_source ,
744
767
need_type = need_type ,
745
768
id = id ,
746
769
content = content ,
0 commit comments