def task_name(self) -> str: """ Generates a simple name suitable for use as a Python function. """ return "_".join(( self.method.name, self.url.scheme, to_identifier(self.url.hostname), to_identifier(self.url.path), str(abs(hash(self))), ))
def task_name(self) -> str: """ Generates a simple name to be used as :attr:`~transformer.task.Task2.name` by the :term:`task` of this request. """ return "_".join(( self.method.name, self.url.scheme, to_identifier(self.url.hostname), to_identifier(self.url.path), str(abs(hash(self))), ))
def from_har_file( cls, path: Path, plugins: Sequence[Plugin], ts_plugins: Sequence[Plugin], short_name: bool, blacklist: Blacklist, ) -> "Scenario": """ Creates a Scenario given a HAR file. :raise SkippableScenarioError: if path is unreadable or not a HAR file """ try: with path.open() as file: har = json.load(file) requests = Request.all_from_har(har) tasks = Task.from_requests(requests, blacklist) # TODO: Remove this when Contract.OnTaskSequence is removed. tasks = plug.apply(ts_plugins, tasks) # TODO: Remove Task-to-Task2 conversion once both are merged. tasks = tuple( plug.apply(plugins, Task2.from_task(t)) for t in tasks) return Scenario( name=to_identifier( path.with_suffix("").name if short_name else str(path)), children=tuple(tasks), origin=path, weight=cls.weight_from_path(path), ) except (OSError, json.JSONDecodeError, UnicodeDecodeError) as err: raise SkippableScenarioError(path, err)
class TestToIdentifier: @given(text(min_size=1, max_size=3)) @example("0") def test_its_output_can_always_be_used_as_python_identifier(self, s: str): exec(f"{to_identifier(s)} = 2") @given(text(), text()) @example("x y", to_identifier("x y")) def test_it_has_no_collisions(self, a: str, b: str): assert a == b or to_identifier(a) != to_identifier(b) @given( from_regex(re.compile(r"[a-z_][a-z0-9_]*", re.IGNORECASE), fullmatch=True)) def test_it_does_not_add_suffix_when_not_necessary(self, input: str): assume(not DIGITS_SUFFIX_RX.search(input)) assert to_identifier(input) == input def test_it_adds_prefix_to_inputs_starting_with_digit(self): assert to_identifier("0").startswith("_")
def test_it_adds_prefix_to_inputs_starting_with_digit(self): assert to_identifier("0").startswith("_")
def test_it_does_not_add_suffix_when_not_necessary(self, input: str): assume(not DIGITS_SUFFIX_RX.search(input)) assert to_identifier(input) == input
def test_it_has_no_collisions(self, a: str, b: str): assert a == b or to_identifier(a) != to_identifier(b)
def from_dir( cls, path: Path, plugins: Sequence[Plugin], ts_plugins: Sequence[Plugin], short_name: bool, blacklist: Blacklist, ) -> "Scenario": """ Makes a :class:`Scenario` out of the provided directory *path*. *path* must represent a "scenario directory", which contains at least one HAR file or another scenario directory. Symbolic link loops are not checked but forbidden! There may exist a weight file :file:`{path}.weight`. If so, its contents will be used as :attr:`weight` after calling :meth:`weight_from_path`. Errors are handled this way: #. If *path* itself cannot be transformed into a scenario, raise :exc:`SkippableScenarioError`. #. For each child of *path*, apply (1) but catch the exception and display a warning about skipping that child. (If all children are skipped, (1) applies to *path* itself.) Therefore: - If the directory contains weight files that don't match any HAR file or subdirectory, an error is emitted as this is probably a mistake. - If the directory contains files or directories that cannot be converted into scenarios (e.g. non-JSON files or :file:`.git` directories), a message is emitted and the file or subdirectory is skipped. :param path: path to the directory. :param plugins: list of :term:`OnScenario` plugins to apply. :param ts_plugins: deprecated -- for backward compatibility only. :param short_name: whether to simplify the resulting :class:`~locust.core.TaskSet` class name. If *short_name* is *False*, that class name is guaranteed to be unique across all TaskSets of the locustfile, but this is generally not necessary and results in less readable class names. :param blacklist: a sequence of urls to be blacklisted :raise SkippableScenarioError: if the directory contains dangling weight files or no sub-scenarios. """ try: children = list(path.iterdir()) except OSError as err: raise SkippableScenarioError(path, err) weight_files: Set[Path] = { child for child in children if child.suffix == WEIGHT_FILE_SUFFIX } scenarios: List[Scenario] = [] for child in children: if child in weight_files: continue try: scenario = cls.from_path( child, plugins, ts_plugins=ts_plugins, short_name=True, blacklist=blacklist, ) except SkippableScenarioError as err: logging.warning( "while searching for HAR files, skipping %s: %s", child, err.reason) else: scenarios.append(scenario) cls._check_dangling_weights(path, scenarios, weight_files) if not scenarios: raise SkippableScenarioError(path, "no scenarios inside the directory") cls._check_name_collisions(path, scenarios) return Scenario( name=to_identifier( path.with_suffix("").name if short_name else str(path)), children=tuple(scenarios), origin=path, weight=cls.weight_from_path(path), )
def from_dir( cls, path: Path, plugins: Sequence[Plugin], ts_plugins: Sequence[Plugin], short_name: bool, ) -> "Scenario": """ Makes a Scenario out of the provided directory path. The directory must be a "scenario directory", which means that it must contain at least one HAR file or another scenario directory. Symbolic link loops are not checked but forbidden! There may exist a weight file <path>.weight. If so, its contents will be used as weight for the Scenario by calling weight_from_path. Errors are handled this way: 1. If path itself cannot be transformed into a scenario, raise SkippableScenarioError. 2. For each child of path, apply (1) but catch the exception and display a warning about skipping this child. (If all children are skipped, (1) applies to path itself.) Therefore: - If the directory contains weight files that don't match any HAR file or subdirectory, an error will be emitted as this is probably a mistake. - If the directory contains files or directory that cannot be converted into scenarios (e.g. non-JSON files or .git directories), a message is emitted and the file or subdirectory is skipped. :raise SkippableScenarioError: if the directory contains dangling weight files or no sub-scenarios. """ try: children = list(path.iterdir()) except OSError as err: raise SkippableScenarioError(path, err) weight_files: Set[Path] = { child for child in children if child.suffix == WEIGHT_FILE_SUFFIX } scenarios: List[Scenario] = [] for child in children: if child in weight_files: continue try: scenario = cls.from_path(child, plugins, ts_plugins=ts_plugins, short_name=True) except SkippableScenarioError as err: logging.warning( "while searching for HAR files, skipping %s: %s", child, err.reason) else: scenarios.append(scenario) cls._check_dangling_weights(path, scenarios, weight_files) if not scenarios: raise SkippableScenarioError(path, "no scenarios inside the directory") cls._check_name_collisions(path, scenarios) return Scenario( name=to_identifier( path.with_suffix("").name if short_name else str(path)), children=tuple(scenarios), origin=path, weight=cls.weight_from_path(path), )