codeplain 0.2.1__py3-none-any.whl → 0.2.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,31 +1,32 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: codeplain
3
- Version: 0.2.1
3
+ Version: 0.2.2
4
4
  Summary: Transform plain language specifications into working code
5
- License-File: LICENSE
6
5
  Classifier: Environment :: Console
7
6
  Classifier: Intended Audience :: Developers
8
7
  Classifier: Operating System :: OS Independent
9
8
  Classifier: Topic :: Software Development :: Code Generators
10
9
  Requires-Python: >=3.11
11
- Requires-Dist: gitpython==3.1.42
12
- Requires-Dist: mistletoe==1.3.0
13
- Requires-Dist: networkx==3.6.1
14
- Requires-Dist: python-frontmatter==1.1.0
10
+ Description-Content-Type: text/markdown
11
+ License-File: LICENSE
15
12
  Requires-Dist: python-liquid2==0.3.0
16
- Requires-Dist: pyyaml==6.0.2
13
+ Requires-Dist: mistletoe==1.3.0
17
14
  Requires-Dist: requests==2.32.3
18
- Requires-Dist: rich==14.2.0
19
- Requires-Dist: textual==1.0.0
20
15
  Requires-Dist: tiktoken==0.12.0
16
+ Requires-Dist: PyYAML==6.0.2
17
+ Requires-Dist: gitpython==3.1.42
21
18
  Requires-Dist: transitions==0.9.3
19
+ Requires-Dist: textual==1.0.0
20
+ Requires-Dist: rich==14.2.0
21
+ Requires-Dist: python-frontmatter==1.1.0
22
+ Requires-Dist: networkx==3.6.1
22
23
  Provides-Extra: dev
23
- Requires-Dist: black==24.2.0; extra == 'dev'
24
- Requires-Dist: flake8==7.0.0; extra == 'dev'
25
- Requires-Dist: isort==5.13.2; extra == 'dev'
26
- Requires-Dist: mypy==1.11.2; extra == 'dev'
27
- Requires-Dist: pytest==8.3.5; extra == 'dev'
28
- Description-Content-Type: text/markdown
24
+ Requires-Dist: pytest==8.3.5; extra == "dev"
25
+ Requires-Dist: flake8==7.0.0; extra == "dev"
26
+ Requires-Dist: black==24.2.0; extra == "dev"
27
+ Requires-Dist: isort==5.13.2; extra == "dev"
28
+ Requires-Dist: mypy==1.11.2; extra == "dev"
29
+ Dynamic: license-file
29
30
 
30
31
  # Codeplain plain2code renderer
31
32
 
@@ -1,17 +1,15 @@
1
1
  codeplain_REST_api.py,sha256=qfzUw9v0-NKII4ibw3vqSBrCeU2WP4RcrrEti43F3zs,18400
2
2
  concept_utils.py,sha256=vwSY4-FmxyqaDBxhntYzqG8t9pXvAWwiULP0DYQI32o,7905
3
- diff_utils.py,sha256=AjiQlqo5pRos_8hVXZo5yBurl5BzSrTMGrQv4dCtRCg,1198
4
3
  event_bus.py,sha256=sduIR3bgIbxAbLhwKd8Gx9YN9gzaeqy9-mNupS04aKw,1759
5
4
  file_utils.py,sha256=4BIxzsteZQOaK-efkvQcoaIfYydsQNFR6elpsxJgXLQ,11591
6
5
  git_utils.py,sha256=gTRps6RIzJJkyy9amaDxP38FPoxYulZViBWr9V0IPQg,12414
7
6
  hash_key.py,sha256=lMKgKpOhPeC4UpFf9e7eCNK20FEaDsXTCJ8j3eCWidE,837
8
- memory_management.py,sha256=ABrM6PhOsalP_PBq2hCazQvQX9C5rpPHhgT35l68RM4,4357
9
7
  module_renderer.py,sha256=LLjLb34phSJlF2YblwGDy5HKWVdi9mo57rr7s-Hj3RA,6261
10
- plain2code.py,sha256=b0VJBnYVtpVZPx1TQZHNsnXREbhdW8V_S8TC-wWQqWw,8970
11
- plain2code_arguments.py,sha256=DHbkWyB33zifROt2SQMlGUC1AZIDJXoJQHlK7Za9b7U,12024
8
+ plain2code.py,sha256=cIxPkxfxZkPlen5RG5H_rvo22sSGYQ9PnqSlw3ECVkY,9841
9
+ plain2code_arguments.py,sha256=PdQjd3orklrtlEyz7-Qdz_m2SvjZtZp6dmbkqXgglSU,11826
12
10
  plain2code_console.py,sha256=-QorOFimS1AWYK7dmFqI3uhjc51cPtEWsaK4DhFibIw,4139
13
11
  plain2code_events.py,sha256=5fPhpRzgJ02xWh0MXqrMv9A4curr2UOE68Y1uKlAcqQ,1347
14
- plain2code_exceptions.py,sha256=UTFovKObkYuIOfknZcEISL06_V5JavnAJsR4rcTubsI,717
12
+ plain2code_exceptions.py,sha256=Y_2Jmv9rLE5xMqlzp_mDcAIIYsIfS0yR1U3scXUzUng,760
15
13
  plain2code_logger.py,sha256=xSDGN8QAWpA4J6YKyj-kfNWSO-jBl0sfUCFRs7Tflf0,4067
16
14
  plain2code_nodes.py,sha256=Om624mfb5MB1Z09c0Zqtb9G1gGkUY9x-v2hzAf3A2gw,3818
17
15
  plain2code_read_config.py,sha256=QnpbW_Bi9LzDIOubM5x7fVXH1HgiFL3-5Oa_O1EUoE4,2449
@@ -22,10 +20,9 @@ plain_modules.py,sha256=iDqqamtix5KahMC_v-vfQ7yndugmqtBW1z6XxTB4x6w,4876
22
20
  plain_spec.py,sha256=zC-VOb_UJOs8OxtEiwQJuonw7Lkmbi7YHyFvvCvUZNo,13529
23
21
  spinner.py,sha256=Ro6Gd9Przf-whuHqPRY6HwI0T57yJjyNPbhDbigZKZE,2471
24
22
  system_config.py,sha256=mgHLn-CRHLO9Y9vKyI_eFBreY_YhFad-ctZgBYp-rIg,1777
23
+ codeplain-0.2.2.dist-info/licenses/LICENSE,sha256=wsFi5dpbJurnRNfBj8q2RCcF3ryrmdRIfxc3lPcmc4c,1069
25
24
  config/__init__.py,sha256=beYSsJWmBNHDP5rYmVDouqgEeP3t1lkkepbXJ-oq0F8,37
26
25
  config/system_config.yaml,sha256=bB5Th5jxgXFyaIvceUPID1ReebMMXsyMibV4gtu9sWQ,1148
27
- docs/generate_cli.py,sha256=xJmiihtdgqEDBYt_wBsRbniZvIfq7Q6tjAsi3SjoMJg,531
28
- examples/example_hello_world_python/harness_tests/hello_world_display/test_hello_world.py,sha256=dwTowrHiVKKbrDv21v8xJC30Q57AXZkQasdGOO5JsBE,470
29
26
  render_machine/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
30
27
  render_machine/code_renderer.py,sha256=jOoYivkZzCuGG947YlNPlvD1Dpd2xTWVK8pwfF_OqDU,2957
31
28
  render_machine/conformance_test_helpers.py,sha256=6Ru7Dh24SLNIKWfz_sP5hE_EmWpvk6nfgN1T1yaCZus,2887
@@ -59,14 +56,6 @@ standard_template_library/golang-console-app-template.plain,sha256=M3gE1wZ6o_F-H
59
56
  standard_template_library/python-console-app-template.plain,sha256=ofIJIkNXScGFTx2w8mY3lP4KmRml2GQv2EiEoXlbqqs,1005
60
57
  standard_template_library/typescript-react-app-boilerplate.plain,sha256=6LFxhEOzWnDHdVpFj-XBTq6s4_2dy7LKV3lVkCzv8i4,114
61
58
  standard_template_library/typescript-react-app-template.plain,sha256=SG1cBMVt1ncMRK4cOGOyVVj0MmsQTmF4MI67IBn1lFg,380
62
- tests/__init__.py,sha256=Wk73Io62J15BtlLVIzxmASDWaaJkQLevS4BLK5LDAQg,16
63
- tests/conftest.py,sha256=QZcp08htUlJGgmHDlRWFgsWXZ8o8IBWTD5QqJaUMlU8,790
64
- tests/test_git_utils.py,sha256=Knc4R2ZkHYVj9iPFKhb0_ewaad_mxPrakOn6gpziHMc,13138
65
- tests/test_imports.py,sha256=cdw7u93xNFD064sjwwEWy4oLHhJNlt1-DRDYhHjymFw,2078
66
- tests/test_plainfile.py,sha256=N3f59hpxOO5zULdBtmXZM6KO2PKADoOL5d3WxNTUYXg,11106
67
- tests/test_plainfileparser.py,sha256=9B9r2jEeUKDMhqb4TJEPK7aatYl1op1z92GDAD4fJ20,18685
68
- tests/test_plainspec.py,sha256=ouS899oejStu8u1D3399y5NAxcKlNbLcinNoxZUp59M,2437
69
- tests/test_requires.py,sha256=u8wY-UI7Ryat84htaI0yFXpl-PjX7G90EnMKM35S6No,1182
70
59
  tui/__init__.py,sha256=_fy7FowY0RkWdn4kC7XV2jgvQPCj-2gE8fNUb-Mny0A,60
71
60
  tui/components.py,sha256=l7f-jLk0sj9WM8z2IpaHksmSyytXe_bl2GBdHASoIg4,13901
72
61
  tui/models.py,sha256=KMjlWubmPD41GA-BjgiqkaV9v7tLJ0fuWKBDPmZj4JA,1493
@@ -74,8 +63,8 @@ tui/plain2code_tui.py,sha256=7agVU0NnaCuF1LuOSEmjx-XfEOQ6HHr1HlWe_b1Tses,11695
74
63
  tui/state_handlers.py,sha256=HbjgaV-9xGhp3E-3X114zOqPkeNcCjT-R1PbVRxVdso,12674
75
64
  tui/styles.css,sha256=Umm2TLePmywizZGV4Nd8UezZRiK5pFyibYRbpRvGqbs,3056
76
65
  tui/widget_helpers.py,sha256=VJorEM2PjRBzN-jIDmKJPolFgo2d8-2NmTumgC5xeNo,5229
77
- codeplain-0.2.1.dist-info/METADATA,sha256=UmRjTWg_BVVg4NqJRvOi_Rb6ldLR4EwZDU4X0TpNI3w,4278
78
- codeplain-0.2.1.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
79
- codeplain-0.2.1.dist-info/entry_points.txt,sha256=oDZkBqu9WhtZApb_K6ia8-fn9aojwmAsgnKELceX5T4,46
80
- codeplain-0.2.1.dist-info/licenses/LICENSE,sha256=wsFi5dpbJurnRNfBj8q2RCcF3ryrmdRIfxc3lPcmc4c,1069
81
- codeplain-0.2.1.dist-info/RECORD,,
66
+ codeplain-0.2.2.dist-info/METADATA,sha256=GdVqb-nYcVTRFWOtusYkzXrEaRJ1XCLoSAv0ErxKSEQ,4300
67
+ codeplain-0.2.2.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
68
+ codeplain-0.2.2.dist-info/entry_points.txt,sha256=oDZkBqu9WhtZApb_K6ia8-fn9aojwmAsgnKELceX5T4,46
69
+ codeplain-0.2.2.dist-info/top_level.txt,sha256=mj1YZAk6MowQ7wZZkVOAcdUJrJKeWQ7IRZnUHHjaFTM,602
70
+ codeplain-0.2.2.dist-info/RECORD,,
@@ -1,4 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: hatchling 1.28.0
2
+ Generator: setuptools (80.10.2)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
+
@@ -0,0 +1,41 @@
1
+ code_complexity
2
+ codeplain
3
+ codeplain_REST_api
4
+ codeplain_constants
5
+ codeplain_local_api
6
+ codeplain_models
7
+ codeplain_types
8
+ codeplain_utils
9
+ concept_utils
10
+ config
11
+ content_extractor
12
+ event_bus
13
+ file_utils
14
+ git_utils
15
+ hash_key
16
+ llm
17
+ llm_exceptions
18
+ llm_handler
19
+ llm_selector
20
+ module_renderer
21
+ plain2code
22
+ plain2code_arguments
23
+ plain2code_console
24
+ plain2code_events
25
+ plain2code_exceptions
26
+ plain2code_logger
27
+ plain2code_nodes
28
+ plain2code_read_config
29
+ plain2code_state
30
+ plain2code_tui
31
+ plain2code_utils
32
+ plain_file
33
+ plain_modules
34
+ plain_spec
35
+ render_cache
36
+ render_machine
37
+ spinner
38
+ standard_template_library
39
+ system_config
40
+ tui
41
+ tui_components
plain2code.py CHANGED
@@ -17,7 +17,7 @@ from event_bus import EventBus
17
17
  from module_renderer import ModuleRenderer
18
18
  from plain2code_arguments import parse_arguments
19
19
  from plain2code_console import console
20
- from plain2code_exceptions import PlainSyntaxError
20
+ from plain2code_exceptions import MissingAPIKey, PlainSyntaxError
21
21
  from plain2code_logger import (
22
22
  CrashLogHandler,
23
23
  IndentedFormatter,
@@ -161,6 +161,17 @@ def render(args, run_state: RunState, codeplain_api, event_bus: EventBus): # no
161
161
 
162
162
  console.info(f"Rendering {args.filename} to target code.")
163
163
 
164
+ # Compute render range from either --render-range or --render-from
165
+ render_range = None
166
+ if args.render_range or args.render_from:
167
+ # Parse the plain file to get the plain_source for FRID extraction
168
+ _, plain_source, _ = plain_file.plain_file_parser(args.filename, template_dirs)
169
+
170
+ if args.render_range:
171
+ render_range = get_render_range(args.render_range, plain_source)
172
+ elif args.render_from:
173
+ render_range = get_render_range_from(args.render_from, plain_source)
174
+
164
175
  codeplainAPI = codeplain_api.CodeplainAPI(args.api_key, console)
165
176
  codeplainAPI.verbose = args.verbose
166
177
  assert args.api is not None and args.api != "", "API URL is required"
@@ -169,7 +180,7 @@ def render(args, run_state: RunState, codeplain_api, event_bus: EventBus): # no
169
180
  module_renderer = ModuleRenderer(
170
181
  codeplainAPI,
171
182
  args.filename,
172
- args.render_range,
183
+ render_range,
173
184
  template_dirs,
174
185
  args,
175
186
  run_state,
@@ -208,6 +219,12 @@ def main():
208
219
  run_state = RunState(spec_filename=args.filename, replay_with=args.replay_with)
209
220
 
210
221
  try:
222
+ # Validate API key is present
223
+ if not args.api_key:
224
+ raise MissingAPIKey(
225
+ "API key is required. Please set the CODEPLAIN_API_KEY environment variable or provide it with the --api-key argument."
226
+ )
227
+
211
228
  render(args, run_state, codeplain_api, event_bus)
212
229
  except InvalidFridArgument as e:
213
230
  console.error(f"Error rendering plain code: {str(e)}.\n")
@@ -237,6 +254,8 @@ def main():
237
254
  console.error(f"Error rendering plain code: {str(e)}\n")
238
255
  console.debug(f"Render ID: {run_state.render_id}")
239
256
  dump_crash_logs(args)
257
+ except MissingAPIKey as e:
258
+ console.error(f"Missing API key: {str(e)}\n")
240
259
  except Exception as e:
241
260
  console.error(f"Error rendering plain code: {str(e)}\n")
242
261
  console.debug(f"Render ID: {run_state.render_id}")
plain2code_arguments.py CHANGED
@@ -5,10 +5,6 @@ import re
5
5
  from plain2code_read_config import get_args_from_config
6
6
 
7
7
  CODEPLAIN_API_KEY = os.getenv("CODEPLAIN_API_KEY")
8
- if not CODEPLAIN_API_KEY:
9
- CLAUDE_API_KEY = os.getenv("CLAUDE_API_KEY")
10
- if not CLAUDE_API_KEY:
11
- raise ValueError("CODEPLAIN_API_KEY or CLAUDE_API_KEY environment variable is not set")
12
8
 
13
9
 
14
10
  DEFAULT_BUILD_FOLDER = "plain_modules"
plain2code_exceptions.py CHANGED
@@ -43,3 +43,7 @@ class MultipleRendersFound(Exception):
43
43
 
44
44
  class UnexpectedState(Exception):
45
45
  pass
46
+
47
+
48
+ class MissingAPIKey(Exception):
49
+ pass
diff_utils.py DELETED
@@ -1,32 +0,0 @@
1
- from difflib import unified_diff
2
-
3
-
4
- def get_unified_diff(filename: str, existing_file_content: str, response_file_content: str) -> str:
5
- diff = unified_diff(
6
- existing_file_content.splitlines(keepends=True),
7
- response_file_content.splitlines(keepends=True),
8
- fromfile=filename,
9
- tofile=filename,
10
- )
11
-
12
- return "".join(diff)
13
-
14
-
15
- def get_code_diff(response_files: dict[str, str], existing_files_content: dict[str, str]) -> dict[str, str]:
16
- code_diff: dict[str, str] = {}
17
- for file_name in response_files:
18
- if file_name in existing_files_content and existing_files_content[file_name]:
19
- if response_files[file_name]:
20
- unified_diff_result = get_unified_diff(
21
- file_name,
22
- existing_files_content[file_name],
23
- response_files[file_name],
24
- )
25
- if unified_diff_result and unified_diff_result.strip():
26
- code_diff[file_name] = unified_diff_result
27
- else:
28
- code_diff[file_name] = f"File {file_name} was deleted."
29
- else:
30
- code_diff[file_name] = response_files[file_name]
31
-
32
- return code_diff
docs/generate_cli.py DELETED
@@ -1,20 +0,0 @@
1
- import os
2
- import sys
3
-
4
- from plain2code_arguments import create_parser
5
-
6
- # Add the parent directory to the path so we can import plain2code_arguments
7
- sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
8
-
9
-
10
- # Get the parser and generate help text
11
- parser = create_parser()
12
- help_text = parser.format_help()
13
-
14
- # Create markdown
15
- md = "# Plain2Code CLI Reference\n\n```text\n" + help_text + "\n```"
16
-
17
- # Run generate_cli.py in the docs folder
18
-
19
- with open("plain2code_cli.md", "w", encoding="utf-8") as f:
20
- f.write(md)
@@ -1,17 +0,0 @@
1
- #!/usr/bin/env python3
2
-
3
- import subprocess
4
- import unittest
5
-
6
-
7
- class TestHelloWorld(unittest.TestCase):
8
- def test_hello_world_output(self):
9
- # Run the hello_world.py script and capture its output
10
- result = subprocess.run(["python3", "hello_world.py"], capture_output=True, text=True)
11
-
12
- # Check if the output matches the expected string
13
- self.assertEqual(result.stdout.strip(), "hello, world")
14
-
15
-
16
- if __name__ == "__main__":
17
- unittest.main()
memory_management.py DELETED
@@ -1,97 +0,0 @@
1
- import os
2
-
3
- import file_utils
4
- from plain2code_console import console
5
- from plain_modules import CODEPLAIN_MEMORY_SUBFOLDER
6
- from render_machine.implementation_code_helpers import ImplementationCodeHelpers
7
- from render_machine.render_context import RenderContext
8
-
9
- CONFORMANCE_TESTS_SUCCESS_EXIT_CODE = 0
10
- CONFORMANCE_TEST_MEMORY_SUBFOLDER = "conformance_test_memory"
11
-
12
-
13
- class MemoryManager:
14
-
15
- @staticmethod
16
- def fetch_memory_files(memory_folder: str):
17
- """Fetch memory files from memory_folder/conformance_test_memory."""
18
- memory_path = os.path.join(memory_folder, CONFORMANCE_TEST_MEMORY_SUBFOLDER)
19
- if not os.path.exists(memory_path):
20
- return {}, {}
21
- memory_files = file_utils.list_all_text_files(memory_path)
22
- memory_files_content = file_utils.get_existing_files_content(memory_path, memory_files)
23
- return memory_files, memory_files_content
24
-
25
- def __init__(self, codeplain_api, module_build_folder: str):
26
- self.codeplain_api = codeplain_api
27
- self.memory_folder = os.path.join(module_build_folder, CODEPLAIN_MEMORY_SUBFOLDER)
28
-
29
- def create_conformance_tests_memory(
30
- self, render_context: RenderContext, exit_code: int, conformance_tests_issue: str
31
- ):
32
-
33
- current_conformance_tests_issue_frid = render_context.conformance_tests_running_context.current_testing_frid
34
- old_conformance_tests_issue_frid = (
35
- render_context.conformance_tests_running_context.previous_conformance_tests_issue_frid
36
- )
37
-
38
- old_conformance_tests_issue = (
39
- render_context.conformance_tests_running_context.previous_conformance_tests_issue_old
40
- )
41
-
42
- is_first_time_running_conformance_tests = (
43
- old_conformance_tests_issue_frid is None or old_conformance_tests_issue_frid == ""
44
- )
45
- is_same_frid_as_previous_failing_test = current_conformance_tests_issue_frid == old_conformance_tests_issue_frid
46
- is_conformance_test_failed = exit_code != CONFORMANCE_TESTS_SUCCESS_EXIT_CODE
47
-
48
- should_create_memory = not is_first_time_running_conformance_tests and (
49
- is_same_frid_as_previous_failing_test or is_conformance_test_failed
50
- )
51
- code_diff_files = render_context.conformance_tests_running_context.code_diff_files
52
-
53
- if not should_create_memory or code_diff_files is None:
54
- console.info(
55
- "Skipping creation of conformance test memory because the conditions for creating memories are not met."
56
- )
57
- return
58
-
59
- existing_files, existing_files_content = ImplementationCodeHelpers.fetch_existing_files(
60
- render_context.build_folder
61
- )
62
- _, memory_files_content = MemoryManager.fetch_memory_files(self.memory_folder)
63
-
64
- conformance_tests_folder_name = (
65
- render_context.conformance_tests_running_context.get_current_conformance_test_folder_name()
66
- )
67
-
68
- (
69
- _,
70
- existing_conformance_test_files_content,
71
- ) = render_context.conformance_tests.fetch_existing_conformance_test_files(
72
- render_context.module_name,
73
- render_context.required_modules,
74
- render_context.conformance_tests_running_context.current_testing_module_name,
75
- conformance_tests_folder_name,
76
- )
77
- acceptance_tests = render_context.conformance_tests_running_context.get_current_acceptance_tests()
78
-
79
- response_files = render_context.codeplain_api.create_conformance_test_memory(
80
- render_context.frid_context.frid,
81
- render_context.plain_source_tree,
82
- render_context.frid_context.linked_resources,
83
- existing_files_content,
84
- memory_files_content,
85
- render_context.module_name,
86
- render_context.get_required_modules_functionalities(),
87
- code_diff_files,
88
- existing_conformance_test_files_content,
89
- acceptance_tests,
90
- conformance_tests_issue,
91
- conformance_tests_folder_name,
92
- old_conformance_tests_issue,
93
- run_state=render_context.run_state,
94
- )
95
- if len(response_files) > 0:
96
- memory_folder_path = os.path.join(self.memory_folder, CONFORMANCE_TEST_MEMORY_SUBFOLDER)
97
- file_utils.store_response_files(memory_folder_path, response_files, existing_files)
tests/__init__.py DELETED
@@ -1 +0,0 @@
1
- # Tests package
tests/conftest.py DELETED
@@ -1,34 +0,0 @@
1
- import os
2
-
3
- import pytest
4
-
5
- os.environ["MASTER_KEY"] = "test-master-key"
6
- os.environ["GOOGLE_API_KEY"] = "test-google-api-key"
7
-
8
-
9
- @pytest.fixture
10
- def test_data_path():
11
- """Returns the path to the test data directory."""
12
- return os.path.dirname(__file__)
13
-
14
-
15
- @pytest.fixture
16
- def load_test_data(test_data_path):
17
- """Returns a function to load test data files."""
18
-
19
- def _load(file_name):
20
- file_path = os.path.join(test_data_path, file_name)
21
- with open(file_path, "r") as file:
22
- return file.read()
23
-
24
- return _load
25
-
26
-
27
- @pytest.fixture
28
- def get_test_data_path(test_data_path):
29
- """Returns a function to get the path to a test data subfolder."""
30
-
31
- def _get_path(subfolder_name):
32
- return os.path.join(test_data_path, subfolder_name)
33
-
34
- return _get_path