|
4 | 4 | import asyncio
|
5 | 5 | import os
|
6 | 6 | import sys
|
| 7 | +import threading |
7 | 8 | import weakref
|
8 | 9 | from abc import ABC, abstractmethod
|
9 | 10 | from collections import OrderedDict
|
@@ -473,67 +474,74 @@ def __init__(self, parent_protocol: RobotLanguageServerProtocol, folder: Uri, co
|
473 | 474 | self.parent_protocol.documents.did_create_uri.add(self._do_imports_changed)
|
474 | 475 | self.parent_protocol.documents.did_change.add(self.resource_document_changed)
|
475 | 476 | self._command_line_variables: Optional[List[VariableDefinition]] = None
|
| 477 | + self._command_line_variables_lock = Lock() |
476 | 478 |
|
477 | 479 | self._python_path: Optional[List[str]] = None
|
| 480 | + self._python_path_lock = threading.RLock() |
478 | 481 | self._environment: Optional[Mapping[str, str]] = None
|
| 482 | + self._environment_lock = threading.RLock() |
479 | 483 |
|
480 | 484 | self._library_files_cache = AsyncSimpleLRUCache()
|
481 | 485 | self._resource_files_cache = AsyncSimpleLRUCache()
|
482 | 486 | self._variables_files_cache = AsyncSimpleLRUCache()
|
483 | 487 |
|
484 | 488 | @property
|
485 | 489 | def environment(self) -> Mapping[str, str]:
|
486 |
| - if self._environment is None: |
487 |
| - self._environment = dict(os.environ) |
| 490 | + with self._environment_lock: |
| 491 | + if self._environment is None: |
| 492 | + self._environment = dict(os.environ) |
488 | 493 |
|
489 |
| - self._environment.update(self.config.env) |
| 494 | + self._environment.update(self.config.env) |
490 | 495 |
|
491 |
| - return self._environment |
| 496 | + return self._environment |
492 | 497 |
|
493 | 498 | @property
|
494 | 499 | def python_path(self) -> List[str]:
|
495 |
| - if self._python_path is None: |
496 |
| - self._python_path = sys.path |
| 500 | + with self._python_path_lock: |
| 501 | + if self._python_path is None: |
| 502 | + self._python_path = sys.path |
497 | 503 |
|
498 |
| - file = Path(__file__).resolve() |
499 |
| - top = file.parents[3] |
500 |
| - for p in filter(lambda v: path_is_relative_to(v, top), sys.path.copy()): |
501 |
| - self._python_path.remove(p) |
| 504 | + file = Path(__file__).resolve() |
| 505 | + top = file.parents[3] |
| 506 | + for p in filter(lambda v: path_is_relative_to(v, top), sys.path.copy()): |
| 507 | + self._python_path.remove(p) |
502 | 508 |
|
503 |
| - for p in self.config.python_path: |
504 |
| - absolute_path = str(Path(p).absolute()) |
505 |
| - if absolute_path not in self._python_path: |
506 |
| - self._python_path.insert(0, absolute_path) |
| 509 | + for p in self.config.python_path: |
| 510 | + absolute_path = str(Path(p).absolute()) |
| 511 | + if absolute_path not in self._python_path: |
| 512 | + self._python_path.insert(0, absolute_path) |
507 | 513 |
|
508 |
| - return self._python_path or [] |
| 514 | + return self._python_path |
509 | 515 |
|
510 | 516 | @_logger.call
|
511 | 517 | async def get_command_line_variables(self) -> List[VariableDefinition]:
|
512 | 518 | from robot.utils.text import split_args_from_name_or_path
|
513 | 519 |
|
514 |
| - if self._command_line_variables is None: |
515 |
| - if self.config is None: |
516 |
| - self._command_line_variables = [] |
517 |
| - else: |
518 |
| - self._command_line_variables = [ |
519 |
| - CommandLineVariableDefinition(0, 0, 0, 0, "", f"${{{k}}}", None, has_value=True, value=(v,)) |
520 |
| - for k, v in self.config.variables.items() |
521 |
| - ] |
522 |
| - for variable_file in self.config.variable_files: |
523 |
| - name, args = split_args_from_name_or_path(variable_file) |
524 |
| - try: |
525 |
| - lib_doc = await self.get_libdoc_for_variables_import( |
526 |
| - name, tuple(args), str(self.folder.to_path()), self |
527 |
| - ) |
528 |
| - if lib_doc is not None: |
529 |
| - self._command_line_variables += lib_doc.variables |
530 |
| - |
531 |
| - except (SystemExit, KeyboardInterrupt, asyncio.CancelledError): |
532 |
| - raise |
533 |
| - except BaseException as e: |
534 |
| - self._logger.exception(e) |
535 |
| - |
536 |
| - return self._command_line_variables |
| 520 | + async with self._command_line_variables_lock: |
| 521 | + if self._command_line_variables is None: |
| 522 | + |
| 523 | + if self.config is None: |
| 524 | + self._command_line_variables = [] |
| 525 | + else: |
| 526 | + self._command_line_variables = [ |
| 527 | + CommandLineVariableDefinition(0, 0, 0, 0, "", f"${{{k}}}", None, has_value=True, value=(v,)) |
| 528 | + for k, v in self.config.variables.items() |
| 529 | + ] |
| 530 | + for variable_file in self.config.variable_files: |
| 531 | + name, args = split_args_from_name_or_path(variable_file) |
| 532 | + try: |
| 533 | + lib_doc = await self.get_libdoc_for_variables_import( |
| 534 | + name, tuple(args), str(self.folder.to_path()), self |
| 535 | + ) |
| 536 | + if lib_doc is not None: |
| 537 | + self._command_line_variables += lib_doc.variables |
| 538 | + |
| 539 | + except (SystemExit, KeyboardInterrupt, asyncio.CancelledError): |
| 540 | + raise |
| 541 | + except BaseException as e: |
| 542 | + self._logger.exception(e) |
| 543 | + |
| 544 | + return self._command_line_variables |
537 | 545 |
|
538 | 546 | @async_tasking_event
|
539 | 547 | async def libraries_changed(sender, libraries: List[LibraryDoc]) -> None: # NOSONAR
|
|
0 commit comments