diff --git a/NOTICE-3RD-PARTY-CONTENT.md b/NOTICE-3RD-PARTY-CONTENT.md index f25258e..443b944 100644 --- a/NOTICE-3RD-PARTY-CONTENT.md +++ b/NOTICE-3RD-PARTY-CONTENT.md @@ -3,7 +3,7 @@ ## Python | Dependency | Version | License | |:-----------|:-------:|--------:| -|types-requests|2.32.0.20240712|Apache 2.0| +|types-requests|2.32.0.20240907|Apache 2.0| |urllib3|2.2.2|MIT| ## Workflows | Dependency | Version | License | diff --git a/docs/index.md b/docs/index.md index 21ecf9a..49b61dd 100644 --- a/docs/index.md +++ b/docs/index.md @@ -7,6 +7,7 @@ - [`velocitas_lib`](./velocitas_lib.md#module-velocitas_lib) - [`velocitas_lib.conan_utils`](./velocitas_lib.conan_utils.md#module-velocitas_libconan_utils) - [`velocitas_lib.docker`](./velocitas_lib.docker.md#module-velocitas_libdocker) +- [`velocitas_lib.file_utils`](./velocitas_lib.file_utils.md#module-velocitas_libfile_utils) - [`velocitas_lib.functional_interface`](./velocitas_lib.functional_interface.md#module-velocitas_libfunctional_interface) - [`velocitas_lib.middleware`](./velocitas_lib.middleware.md#module-velocitas_libmiddleware) - [`velocitas_lib.services`](./velocitas_lib.services.md#module-velocitas_libservices) @@ -48,6 +49,10 @@ - [`docker.container_exists`](./velocitas_lib.docker.md#function-container_exists): Check if a container with a given name exists. - [`docker.is_docker_image_build_locally`](./velocitas_lib.docker.md#function-is_docker_image_build_locally): Check if vehicle app docker image is locally available - [`docker.push_docker_image_to_registry`](./velocitas_lib.docker.md#function-push_docker_image_to_registry): Push docker image to local image registry +- [`file_utils.capture_area_in_file`](./velocitas_lib.file_utils.md#function-capture_area_in_file): Capture an area of a textfile between a matching start line (exclusive) and the first line matching end_line (exclusive). +- [`file_utils.read_file`](./velocitas_lib.file_utils.md#function-read_file): Reads the file with the given file_path and returns it's content as a str. +- [`file_utils.replace_text_in_file`](./velocitas_lib.file_utils.md#function-replace_text_in_file): Replace all occurrences of text in a file with a replacement. +- [`file_utils.write_file`](./velocitas_lib.file_utils.md#function-write_file): Writes the content to the file_path and returns the success of the write operation. - [`functional_interface.get_interfaces_for_type`](./velocitas_lib.functional_interface.md#function-get_interfaces_for_type): Return all interfaces for the given type. - [`middleware.get_middleware_type`](./velocitas_lib.middleware.md#function-get_middleware_type): Return the current middleware type. - [`services.get_service_port`](./velocitas_lib.services.md#function-get_service_port): Return the service port as string for the specified service. @@ -56,11 +61,9 @@ - [`services.parse_service_config`](./velocitas_lib.services.md#function-parse_service_config): Parse service spec configuration and return it as an named tuple. - [`services.resolve_functions`](./velocitas_lib.services.md#function-resolve_functions) - [`templates.copy_templates`](./velocitas_lib.templates.md#function-copy_templates): Copy templates from the template dir to the target dir. -- [`text_utils.capture_area_in_file`](./velocitas_lib.text_utils.md#function-capture_area_in_file): Capture an area of a textfile between a matching start line (exclusive) and the first line matching end_line (exclusive). - [`text_utils.create_truncated_string`](./velocitas_lib.text_utils.md#function-create_truncated_string): Create a truncated version of input if it is longer than length. - [`text_utils.replace_item_in_list`](./velocitas_lib.text_utils.md#function-replace_item_in_list): Replace the whole line which matches the given text with a replacement. - [`text_utils.replace_text_area`](./velocitas_lib.text_utils.md#function-replace_text_area): Replace all occurrences of all text areas matching the parameters with a replacement. -- [`text_utils.replace_text_in_file`](./velocitas_lib.text_utils.md#function-replace_text_in_file): Replace all occurrences of text in a file with a replacement. - [`text_utils.to_camel_case`](./velocitas_lib.text_utils.md#function-to_camel_case): Return a camel case version of a snake case string. - [`variables.json_obj_to_flat_map`](./velocitas_lib.variables.md#function-json_obj_to_flat_map): Flatten a JSON Object into a one dimensional dict by joining the keys diff --git a/docs/velocitas_lib.file_utils.md b/docs/velocitas_lib.file_utils.md new file mode 100644 index 0000000..17e8ee6 --- /dev/null +++ b/docs/velocitas_lib.file_utils.md @@ -0,0 +1,120 @@ + + + + +# module `velocitas_lib.file_utils` + + + + + +--- + + + +## function `replace_text_in_file` + +```python +replace_text_in_file(file_path: str, text: str, replacement: str) → None +``` + +Replace all occurrences of text in a file with a replacement. + + + +**Args:** + + - `file_path` (str): The path to the file. + - `text` (str): The text to find. + - `replacement` (str): The replacement for text. + + +--- + + + +## function `capture_area_in_file` + +```python +capture_area_in_file( + file: TextIOWrapper, + start_line: str, + end_line: str, + map_fn: Optional[Callable[[str], str]] = None +) → List[str] +``` + +Capture an area of a textfile between a matching start line (exclusive) and the first line matching end_line (exclusive). + + + +**Args:** + + - `file` (TextIOWrapper): The text file to read from. + - `start_line` (str): The line which triggers the capture (will not be part of the output) + - `end_line` (str): The line which terminates the capture (will not be bart of the output) + - `map_fn` (Optional[Callable[[str], str]], optional): An optional mapping function to transform captured lines. Defaults to None. + + + +**Returns:** + + - `List[str]`: A list of captured lines. + + +--- + + + +## function `read_file` + +```python +read_file(file_path: str) → Optional[str] +``` + +Reads the file with the given file_path and returns it's content as a str. + + + +**Args:** + + - `file_path` (str): the file_path of the file to read. + + + +**Returns:** + + - `str`: the content of the specified file. + + +--- + + + +## function `write_file` + +```python +write_file(file_path: str, content: str) → bool +``` + +Writes the content to the file_path and returns the success of the write operation. + + + +**Args:** + + - `file_path` (str): the file_path of the file to write. + - `content` (str): the content to be written to the file. + + + +**Returns:** + + - `bool`: True if writing was successful, False otherwise. + + + + +--- + +_This file was automatically generated via [lazydocs](https://github.com/ml-tooling/lazydocs)._ diff --git a/docs/velocitas_lib.text_utils.md b/docs/velocitas_lib.text_utils.md index df14dd8..3edca8c 100644 --- a/docs/velocitas_lib.text_utils.md +++ b/docs/velocitas_lib.text_utils.md @@ -10,7 +10,7 @@ --- - + ## function `to_camel_case` @@ -35,7 +35,7 @@ Return a camel case version of a snake case string. --- - + ## function `create_truncated_string` @@ -61,28 +61,7 @@ Create a truncated version of input if it is longer than length. Will keep the r --- - - -## function `replace_text_in_file` - -```python -replace_text_in_file(file_path: str, text: str, replacement: str) → None -``` - -Replace all occurrences of text in a file with a replacement. - - - -**Args:** - - - `file_path` (str): The path to the file. - - `text` (str): The text to find. - - `replacement` (str): The replacement for text. - - ---- - - + ## function `replace_item_in_list` @@ -109,7 +88,7 @@ Replace the whole line which matches the given text with a replacement. --- - + ## function `replace_text_area` @@ -134,39 +113,6 @@ Replace all occurrences of all text areas matching the parameters with a replace - `replacement` (str): The replacement for text area. ---- - - - -## function `capture_area_in_file` - -```python -capture_area_in_file( - file: TextIOWrapper, - start_line: str, - end_line: str, - map_fn: Optional[Callable[[str], str]] = None -) → List[str] -``` - -Capture an area of a textfile between a matching start line (exclusive) and the first line matching end_line (exclusive). - - - -**Args:** - - - `file` (TextIOWrapper): The text file to read from. - - `start_line` (str): The line which triggers the capture (will not be part of the output) - - `end_line` (str): The line which terminates the capture (will not be bart of the output) - - `map_fn` (Optional[Callable[[str], str]], optional): An optional mapping function to transform captured lines. Defaults to None. - - - -**Returns:** - - - `List[str]`: A list of captured lines. - - --- diff --git a/tests/test_file_utils.py b/tests/test_file_utils.py new file mode 100644 index 0000000..f392a93 --- /dev/null +++ b/tests/test_file_utils.py @@ -0,0 +1,58 @@ +# Copyright (c) 2024 Contributors to the Eclipse Foundation +# +# This program and the accompanying materials are made available under the +# terms of the Apache License, Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0. +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +# SPDX-License-Identifier: Apache-2.0 + +import os +import tempfile + +import pytest + +from velocitas_lib.file_utils import ( + read_file, + write_file, +) + + +@pytest.fixture +def temp_file(): + temp_file = tempfile.NamedTemporaryFile(delete=False) + yield temp_file + + if os.path.exists(temp_file.name): + os.remove(temp_file.name) + + +def test_write_file(temp_file): + temp_file_path = temp_file.name + write_file( + temp_file_path, + "Lorem ipsum dolor sit amet ...\n1...2...3...", + ) + + assert os.path.exists(temp_file.name) + + read_file_content = temp_file.readlines() + assert read_file_content[0] == b"Lorem ipsum dolor sit amet ...\n" + assert read_file_content[1] == b"1...2...3..." + + +def test_read_file(temp_file): + file_content = "Lorem ipsum dolor sit amet ...\n1...2...3..." + temp_file.write(file_content.encode("utf-8")) + temp_file.flush() + temp_file.close() + + temp_file_path = temp_file.name + read_file_content = read_file(temp_file_path) + + assert read_file_content == file_content diff --git a/velocitas_lib/file_utils.py b/velocitas_lib/file_utils.py new file mode 100644 index 0000000..41093a4 --- /dev/null +++ b/velocitas_lib/file_utils.py @@ -0,0 +1,117 @@ +# Copyright (c) 2024 Contributors to the Eclipse Foundation +# +# This program and the accompanying materials are made available under the +# terms of the Apache License, Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0. +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +# SPDX-License-Identifier: Apache-2.0 + +from io import TextIOWrapper +from typing import Callable, List, Optional + +from velocitas_lib.text_utils import replace_item_in_list + + +def replace_text_in_file(file_path: str, text: str, replacement: str) -> None: + """Replace all occurrences of text in a file with a replacement. + + Args: + file_path (str): The path to the file. + text (str): The text to find. + replacement (str): The replacement for text. + """ + + with open(file_path, mode="r+", encoding="utf-8") as file: + file_text = file.readlines() + replaced_text_list = replace_item_in_list(file_text, text, replacement) + replaced_text = "".join(replaced_text_list) + # replace old content + file.seek(0) + file.write(replaced_text) + file.truncate() + + +def capture_area_in_file( + file: TextIOWrapper, + start_line: str, + end_line: str, + map_fn: Optional[Callable[[str], str]] = None, +) -> List[str]: + """Capture an area of a textfile between a matching start line (exclusive) and the first line matching end_line (exclusive). + + Args: + file (TextIOWrapper): The text file to read from. + start_line (str): The line which triggers the capture (will not be part of the output) + end_line (str): The line which terminates the capture (will not be bart of the output) + map_fn (Optional[Callable[[str], str]], optional): An optional mapping function to transform captured lines. Defaults to None. + + Returns: + List[str]: A list of captured lines. + """ + area_content: List[str] = [] + is_capturing = False + for line in file: + if line.strip() == start_line: + is_capturing = True + elif line.strip() == end_line: + is_capturing = False + elif is_capturing: + line = line.rstrip() + + if map_fn: + line = map_fn(line) + + area_content.append(line) + return area_content + + +def read_file( + file_path: str, +) -> Optional[str]: + """Reads the file with the given file_path and returns it's content as a str. + + Args: + file_path (str): the file_path of the file to read. + + Returns: + str: the content of the specified file. + """ + + try: + with open(file_path, "r") as file: + file_content = file.read() + return file_content + except FileNotFoundError: + print(f"File {file_path} not found") + except Exception as e: + print(f"An error occurred: {e}") + return None + + +def write_file( + file_path: str, + content: str, +) -> bool: + """Writes the content to the file_path and returns the success of the write operation. + + Args: + file_path (str): the file_path of the file to write. + content (str): the content to be written to the file. + + Returns: + bool: True if writing was successful, False otherwise. + """ + + try: + with open(file_path, "w") as file: + file.write(content) + return True + except Exception as e: + print(f"An error occurred: {e}") + return False diff --git a/velocitas_lib/text_utils.py b/velocitas_lib/text_utils.py index b302b38..23bbd0c 100644 --- a/velocitas_lib/text_utils.py +++ b/velocitas_lib/text_utils.py @@ -12,8 +12,7 @@ # # SPDX-License-Identifier: Apache-2.0 -from io import TextIOWrapper -from typing import Callable, List, Optional +from typing import List def to_camel_case(snake_str: str) -> str: @@ -46,25 +45,6 @@ def create_truncated_string(input: str, length: int) -> str: return f"...{input[-length+3:]}" # noqa: E226 intended behaviour -def replace_text_in_file(file_path: str, text: str, replacement: str) -> None: - """Replace all occurrences of text in a file with a replacement. - - Args: - file_path (str): The path to the file. - text (str): The text to find. - replacement (str): The replacement for text. - """ - - with open(file_path, mode="r+", encoding="utf-8") as file: - file_text = file.readlines() - replaced_text_list = replace_item_in_list(file_text, text, replacement) - replaced_text = "".join(replaced_text_list) - # replace old content - file.seek(0) - file.write(replaced_text) - file.truncate() - - def replace_item_in_list( text: List[str], matching_text: str, @@ -125,37 +105,3 @@ def replace_text_area( buffer.append(replacement) return buffer - - -def capture_area_in_file( - file: TextIOWrapper, - start_line: str, - end_line: str, - map_fn: Optional[Callable[[str], str]] = None, -) -> List[str]: - """Capture an area of a textfile between a matching start line (exclusive) and the first line matching end_line (exclusive). - - Args: - file (TextIOWrapper): The text file to read from. - start_line (str): The line which triggers the capture (will not be part of the output) - end_line (str): The line which terminates the capture (will not be bart of the output) - map_fn (Optional[Callable[[str], str]], optional): An optional mapping function to transform captured lines. Defaults to None. - - Returns: - List[str]: A list of captured lines. - """ - area_content: List[str] = [] - is_capturing = False - for line in file: - if line.strip() == start_line: - is_capturing = True - elif line.strip() == end_line: - is_capturing = False - elif is_capturing: - line = line.rstrip() - - if map_fn: - line = map_fn(line) - - area_content.append(line) - return area_content