rbx.cp 0.8.0__py3-none-any.whl → 0.9.0__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.
Files changed (47) hide show
  1. rbx/box/cd.py +2 -2
  2. rbx/box/cli.py +8 -2
  3. rbx/box/code.py +2 -2
  4. rbx/box/contest/build_contest_statements.py +2 -2
  5. rbx/box/contest/contest_package.py +1 -1
  6. rbx/box/contest/main.py +29 -2
  7. rbx/box/environment.py +140 -80
  8. rbx/box/formatting.py +2 -1
  9. rbx/box/package.py +5 -5
  10. rbx/box/packaging/__init__.py +0 -0
  11. rbx/box/packaging/boca/__init__.py +0 -0
  12. rbx/box/packaging/polygon/packager.py +3 -3
  13. rbx/box/presets/__init__.py +369 -53
  14. rbx/box/presets/lock_schema.py +42 -2
  15. rbx/box/presets/schema.py +4 -0
  16. rbx/box/remote.py +3 -3
  17. rbx/box/retries.py +3 -2
  18. rbx/box/sanitizers/warning_stack.py +2 -2
  19. rbx/box/solutions.py +24 -18
  20. rbx/box/statements/build_statements.py +6 -6
  21. rbx/box/statements/builders.py +1 -1
  22. rbx/box/stresses.py +2 -2
  23. rbx/box/testcase_utils.py +3 -3
  24. rbx/grading/judge/sandbox.py +2 -1
  25. rbx/grading/judge/sandboxes/isolate.py +3 -2
  26. rbx/grading/judge/sandboxes/stupid_sandbox.py +3 -2
  27. rbx/grading/judge/storage.py +2 -1
  28. rbx/grading/steps.py +2 -1
  29. rbx/resources/envs/default.rbx.yml +2 -3
  30. rbx/resources/envs/isolate.rbx.yml +2 -3
  31. rbx/resources/presets/default/contest/.gitignore +5 -1
  32. rbx/resources/presets/default/contest/statement/contest.rbx.tex +0 -1
  33. rbx/resources/presets/default/env.rbx.yml +67 -0
  34. rbx/resources/presets/default/preset.rbx.yml +6 -2
  35. rbx/resources/presets/default/problem/.gitignore +1 -1
  36. rbx/resources/presets/default/{contest/statement/template.rbx.tex → shared/problem_template.rbx.tex} +13 -7
  37. rbx/submitors/codeforces.py +3 -2
  38. rbx/test.py +1 -1
  39. rbx/utils.py +6 -1
  40. {rbx_cp-0.8.0.dist-info → rbx_cp-0.9.0.dist-info}/METADATA +2 -1
  41. {rbx_cp-0.8.0.dist-info → rbx_cp-0.9.0.dist-info}/RECORD +46 -44
  42. rbx/resources/presets/default/problem/statement/icpc.sty +0 -322
  43. /rbx/resources/presets/default/{problem/statement/template.rbx.tex → shared/contest_template.rbx.tex} +0 -0
  44. /rbx/resources/presets/default/{contest/statement → shared}/icpc.sty +0 -0
  45. {rbx_cp-0.8.0.dist-info → rbx_cp-0.9.0.dist-info}/LICENSE +0 -0
  46. {rbx_cp-0.8.0.dist-info → rbx_cp-0.9.0.dist-info}/WHEEL +0 -0
  47. {rbx_cp-0.8.0.dist-info → rbx_cp-0.9.0.dist-info}/entry_points.txt +0 -0
rbx/box/remote.py CHANGED
@@ -5,7 +5,7 @@ from typing import List, Optional, Tuple, Union
5
5
 
6
6
  import typer
7
7
 
8
- from rbx import console
8
+ from rbx import console, utils
9
9
  from rbx.box import cd, package
10
10
  from rbx.box.formatting import href, ref
11
11
 
@@ -85,7 +85,7 @@ REGISTERED_EXPANDERS: List['Expander'] = [
85
85
 
86
86
 
87
87
  def _relative_to_pkg(path: pathlib.Path) -> pathlib.Path:
88
- return path.resolve().relative_to(pathlib.Path.cwd())
88
+ return utils.abspath(path).relative_to(pathlib.Path.cwd())
89
89
 
90
90
 
91
91
  def _try_cacheable_paths(
@@ -167,4 +167,4 @@ def expand_file(file: str) -> pathlib.Path:
167
167
 
168
168
  def is_path_remote(path: pathlib.Path) -> bool:
169
169
  remote_dir = package.get_problem_remote_dir()
170
- return path.resolve().is_relative_to(remote_dir.resolve())
170
+ return utils.abspath(path).is_relative_to(utils.abspath(remote_dir))
rbx/box/retries.py CHANGED
@@ -5,6 +5,7 @@ import tempfile
5
5
  from contextlib import contextmanager
6
6
  from typing import Awaitable, Callable, List, Optional
7
7
 
8
+ from rbx import utils
8
9
  from rbx.box import package
9
10
  from rbx.box.setter_config import RepeatsConfig, get_setter_config
10
11
  from rbx.grading.steps import Evaluation, Outcome
@@ -59,8 +60,8 @@ class FileToRecover:
59
60
 
60
61
  def _move_to_temp_dir(path: pathlib.Path, temp_dir: pathlib.Path) -> FileToRecover:
61
62
  problem_path = package.find_problem()
62
- path = path.resolve()
63
- temp_dir = temp_dir.resolve()
63
+ path = utils.abspath(path)
64
+ temp_dir = utils.abspath(temp_dir)
64
65
  relative = path.relative_to(problem_path)
65
66
 
66
67
  temp_path = temp_dir / relative
@@ -2,7 +2,7 @@ import functools
2
2
  import pathlib
3
3
  import shutil
4
4
 
5
- from rbx import console
5
+ from rbx import console, utils
6
6
  from rbx.box.schema import CodeItem
7
7
  from rbx.grading.judge.cacher import FileCacher
8
8
  from rbx.grading.steps import GradingFileOutput
@@ -60,7 +60,7 @@ def _get_warning_runs_dir(root: pathlib.Path) -> pathlib.Path:
60
60
 
61
61
 
62
62
  def get_warning_stack() -> WarningStack:
63
- current_root = pathlib.Path.cwd().resolve()
63
+ current_root = utils.abspath(pathlib.Path.cwd())
64
64
  return _get_warning_stack(current_root)
65
65
 
66
66
 
rbx/box/solutions.py CHANGED
@@ -54,6 +54,7 @@ from rbx.box.testcase_utils import (
54
54
  parse_interaction,
55
55
  print_interaction,
56
56
  )
57
+ from rbx.grading import grading_context
57
58
  from rbx.grading.limits import Limits
58
59
  from rbx.grading.steps import (
59
60
  Evaluation,
@@ -498,7 +499,7 @@ async def _generate_testcase_interactively(
498
499
  console.console.print(testcase.inputPath.read_text())
499
500
  else:
500
501
  console.console.print(
501
- f'Input was written to [item]{testcase.inputPath.resolve()}[/item]'
502
+ f'Input was written to [item]{utils.abspath(testcase.inputPath)}[/item]'
502
503
  )
503
504
  console.console.print()
504
505
 
@@ -660,23 +661,28 @@ async def run_and_print_interactive_solutions(
660
661
  tracked_solutions,
661
662
  verification=verification,
662
663
  )
663
- testcase = await _generate_testcase_interactively(
664
- progress=progress,
665
- generator=generator,
666
- testcase_entry=testcase_entry,
667
- check=check,
668
- custom_output=custom_output,
669
- sanitized=sanitized,
670
- print=print,
671
- )
672
- items = _run_interactive_solutions(
673
- testcase,
674
- skeleton=skeleton,
675
- progress=progress,
676
- verification=verification,
677
- check=check,
678
- sanitized=sanitized,
679
- )
664
+
665
+ should_cache = testcase_entry is not None
666
+ with grading_context.cache_level(
667
+ grading_context.CacheLevel.CACHE_COMPILATION, when=not should_cache
668
+ ):
669
+ testcase = await _generate_testcase_interactively(
670
+ progress=progress,
671
+ generator=generator,
672
+ testcase_entry=testcase_entry,
673
+ check=check,
674
+ custom_output=custom_output,
675
+ sanitized=sanitized,
676
+ print=print,
677
+ )
678
+ items = _run_interactive_solutions(
679
+ testcase,
680
+ skeleton=skeleton,
681
+ progress=progress,
682
+ verification=verification,
683
+ check=check,
684
+ sanitized=sanitized,
685
+ )
680
686
 
681
687
  for item in items:
682
688
  sol = skeleton.find_solution_skeleton(item.solution)
@@ -6,7 +6,7 @@ from typing import Annotated, Any, Dict, List, Optional, Tuple
6
6
  import syncer
7
7
  import typer
8
8
 
9
- from rbx import annotations, console
9
+ from rbx import annotations, console, utils
10
10
  from rbx.box import environment, naming, package
11
11
  from rbx.box.formatting import href
12
12
  from rbx.box.schema import Package, expand_any_vars
@@ -46,7 +46,7 @@ def get_environment_languages_for_statement() -> List[StatementCodeLanguage]:
46
46
  res.append(
47
47
  StatementCodeLanguage(
48
48
  id=language.name,
49
- name=language.readable_name or language.name,
49
+ name=language.readableName or language.name,
50
50
  command=cmd or '',
51
51
  )
52
52
  )
@@ -173,7 +173,7 @@ def get_relative_assets(
173
173
  relative_to: pathlib.Path,
174
174
  assets: List[str],
175
175
  ) -> List[Tuple[pathlib.Path, pathlib.Path]]:
176
- relative_to = relative_to.resolve()
176
+ relative_to = utils.abspath(relative_to)
177
177
  if not relative_to.is_dir():
178
178
  relative_to = relative_to.parent
179
179
  res = []
@@ -192,7 +192,7 @@ def get_relative_assets(
192
192
  raise typer.Exit(1)
193
193
  res.extend(get_relative_assets(relative_to, list(map(str, globbed))))
194
194
  continue
195
- if not relative_path.resolve().is_relative_to(relative_to):
195
+ if not utils.abspath(relative_path).is_relative_to(relative_to):
196
196
  console.console.print(
197
197
  f'[error]Asset [item]{asset}[/item] is not relative to your statement.[/error]'
198
198
  )
@@ -200,8 +200,8 @@ def get_relative_assets(
200
200
 
201
201
  res.append(
202
202
  (
203
- relative_path.resolve(),
204
- relative_path.resolve().relative_to(relative_to),
203
+ utils.abspath(relative_path),
204
+ utils.abspath(relative_path).relative_to(relative_to),
205
205
  )
206
206
  )
207
207
 
@@ -319,7 +319,7 @@ class rbxTeXBuilder(StatementBuilder):
319
319
  params = typing.cast(rbxToTeX, params)
320
320
  if not params.template:
321
321
  return []
322
- return [((root / params.template).resolve(), params.template)]
322
+ return [(utils.abspath(root / params.template), params.template)]
323
323
 
324
324
  def build(
325
325
  self,
rbx/box/stresses.py CHANGED
@@ -9,7 +9,7 @@ import syncer
9
9
  import typer
10
10
  from pydantic import BaseModel
11
11
 
12
- from rbx import console
12
+ from rbx import console, utils
13
13
  from rbx.box import checkers, generators, package, tasks, validators
14
14
  from rbx.box.code import SanitizationLevel, compile_item
15
15
  from rbx.box.generators import (
@@ -311,7 +311,7 @@ def print_stress_report(report: StressReport):
311
311
  console.console.print(f'Found [item]{len(report.findings)}[/item] testcases.')
312
312
 
313
313
  findings_dir = package.get_problem_runs_dir() / '.stress' / 'findings'
314
- console.console.print(f'Findings: {findings_dir.resolve()}')
314
+ console.console.print(f'Findings: {utils.abspath(findings_dir)}')
315
315
  console.console.print()
316
316
 
317
317
  for i, finding in enumerate(report.findings):
rbx/box/testcase_utils.py CHANGED
@@ -7,7 +7,7 @@ import rich.text
7
7
  import typer
8
8
  from pydantic import BaseModel
9
9
 
10
- from rbx import console
10
+ from rbx import console, utils
11
11
  from rbx.box import package
12
12
  from rbx.box.package import get_build_testgroup_path, get_build_tests_path
13
13
  from rbx.box.schema import Testcase, TestcaseGroup
@@ -141,8 +141,8 @@ def get_samples() -> List[Testcase]:
141
141
  tcs = find_built_testcases(package.get_testgroup('samples'))
142
142
  return [
143
143
  Testcase(
144
- inputPath=tc.inputPath.resolve(),
145
- outputPath=tc.outputPath.resolve()
144
+ inputPath=utils.abspath(tc.inputPath),
145
+ outputPath=utils.abspath(tc.outputPath)
146
146
  if tc.outputPath is not None and tc.outputPath.is_file()
147
147
  else None,
148
148
  )
@@ -16,6 +16,7 @@ from typing import IO, Any, Dict, List, Optional
16
16
 
17
17
  import pydantic
18
18
 
19
+ from rbx import utils
19
20
  from rbx.grading.judge import cacher, storage
20
21
 
21
22
  logger = logging.getLogger(__name__)
@@ -468,7 +469,7 @@ class SandboxBase(abc.ABC):
468
469
  if override:
469
470
  real_path.unlink(missing_ok=True)
470
471
  try:
471
- real_path.symlink_to(from_path.resolve())
472
+ real_path.symlink_to(utils.abspath(from_path))
472
473
  except NotImplementedError:
473
474
  return None
474
475
  return real_path
@@ -9,6 +9,7 @@ import subprocess
9
9
  import tempfile
10
10
  from typing import IO, Any, Dict, List, Optional
11
11
 
12
+ from rbx import utils
12
13
  from rbx.config import get_app_path
13
14
  from rbx.grading.judge.cacher import FileCacher
14
15
  from rbx.grading.judge.sandbox import (
@@ -180,10 +181,10 @@ class IsolateSandbox(SandboxBase):
180
181
  """
181
182
  outer_paths: List[pathlib.Path] = []
182
183
  for inner_path in inner_paths:
183
- abs_inner_path = (self._home_dest / inner_path).resolve()
184
+ abs_inner_path = utils.abspath(self._home_dest / inner_path)
184
185
  # If an inner path is absolute (e.g., /fifo0/u0_to_m) then
185
186
  # it may be outside home and we should ignore it.
186
- if not abs_inner_path.is_relative_to(self._home_dest.resolve()):
187
+ if not abs_inner_path.is_relative_to(utils.abspath(self._home_dest)):
187
188
  continue
188
189
  rel_inner_path = abs_inner_path.relative_to(self._home_dest)
189
190
  outer_path = self._home / rel_inner_path
@@ -11,6 +11,7 @@ import sys
11
11
  import tempfile
12
12
  from typing import Any, Dict, List, Optional
13
13
 
14
+ from rbx import utils
14
15
  from rbx.grading.judge.cacher import FileCacher
15
16
  from rbx.grading.judge.sandbox import (
16
17
  SandboxBase,
@@ -303,8 +304,8 @@ class StupidSandbox(SandboxBase):
303
304
  real_command = (
304
305
  [
305
306
  sys.executable,
306
- str(self.get_timeit_executable().resolve()),
307
- str(self.relative_path(self.get_current_log_name()).resolve()),
307
+ str(utils.abspath(self.get_timeit_executable())),
308
+ str(utils.abspath(self.relative_path(self.get_current_log_name()))),
308
309
  ]
309
310
  + self.get_timeit_args()
310
311
  + command
@@ -10,6 +10,7 @@ from typing import IO, AnyStr, Dict, List, Optional, Type, TypeVar
10
10
  import lz4.frame
11
11
  from pydantic import BaseModel
12
12
 
13
+ from rbx import utils
13
14
  from rbx.grading import grading_context
14
15
 
15
16
  logger = logging.getLogger(__name__)
@@ -408,7 +409,7 @@ class FilesystemStorage(Storage):
408
409
  def filename_from_symlink(self, link: pathlib.Path) -> Optional[str]:
409
410
  if not link.is_symlink():
410
411
  return None
411
- filename = link.readlink().resolve()
412
+ filename = utils.abspath(link.readlink())
412
413
  if not filename.is_file():
413
414
  return None
414
415
  return str(filename.relative_to(self.path))
rbx/grading/steps.py CHANGED
@@ -523,7 +523,8 @@ def _get_system_bits_stdcpp(command: str) -> Optional[GradingFileInput]:
523
523
  if not bits_candidate.is_file():
524
524
  continue
525
525
  return GradingFileInput(
526
- src=bits_candidate.resolve().absolute(), dest=pathlib.Path('bits/stdc++.h')
526
+ src=utils.abspath(bits_candidate),
527
+ dest=pathlib.Path('bits/stdc++.h'),
527
528
  )
528
529
  return None
529
530
 
@@ -18,7 +18,7 @@ defaultExecution:
18
18
  memoryLimit: 1024 # 1gb
19
19
  languages:
20
20
  - name: "cpp"
21
- readable_name: "C++17"
21
+ readableName: "C++17"
22
22
  extension: "cpp"
23
23
  compilation:
24
24
  commands:
@@ -28,10 +28,9 @@ languages:
28
28
  fileMapping:
29
29
  compilable: "compilable.cpp"
30
30
  - name: "py"
31
- readable_name: "Python3"
31
+ readableName: "Python3"
32
32
  extension: "py"
33
33
  execution:
34
34
  command: "python3 {executable}"
35
35
  fileMapping:
36
36
  executable: "executable.py"
37
-
@@ -18,7 +18,7 @@ defaultExecution:
18
18
  memoryLimit: 1024 # 1gb
19
19
  languages:
20
20
  - name: "cpp"
21
- readable_name: "C++17"
21
+ readableName: "C++17"
22
22
  extension: "cpp"
23
23
  compilation:
24
24
  commands:
@@ -28,10 +28,9 @@ languages:
28
28
  fileMapping:
29
29
  compilable: "compilable.cpp"
30
30
  - name: "py"
31
- readable_name: "Python3"
31
+ readableName: "Python3"
32
32
  extension: "py"
33
33
  execution:
34
34
  command: "/usr/bin/python3 {executable}"
35
35
  fileMapping:
36
36
  executable: "executable.py"
37
-
@@ -1,2 +1,6 @@
1
- build/
2
1
  .box/
2
+ build/
3
+
4
+ *.o
5
+ *.aux
6
+ *.log
@@ -33,4 +33,3 @@
33
33
 
34
34
  \label{lastpage}
35
35
  \end{document}
36
-
@@ -0,0 +1,67 @@
1
+ ---
2
+ sandbox: "stupid"
3
+ defaultCompilation:
4
+ sandbox:
5
+ maxProcesses: 1000
6
+ timeLimit: 50000 # 50 seconds
7
+ wallTimeLimit: 50000 # 50 seconds
8
+ memoryLimit: 1024 # 1gb
9
+ defaultExecution:
10
+ sandbox:
11
+ # Useful for checkers, validators, etc.
12
+ timeLimit: 50000 # 50 seconds
13
+ wallTimeLimit: 50000 # 50 seconds
14
+ memoryLimit: 1024 # 1gb
15
+ languages:
16
+ - name: "cpp"
17
+ readableName: "C++20"
18
+ extension: "cpp"
19
+ compilation:
20
+ commands: ["g++ -std=c++20 -O2 -o {executable} {compilable}"]
21
+ execution:
22
+ command: "./{executable}"
23
+ fileMapping:
24
+ compilable: "compilable.cpp"
25
+ extensions:
26
+ boca:
27
+ bocaLanguage: "cc"
28
+ - name: "c"
29
+ readableName: "C"
30
+ extension: "c"
31
+ compilation:
32
+ commands: ["gcc -std=gnu11 -O2 -lm -o {executable} {compilable}"]
33
+ execution:
34
+ command: "./{executable}"
35
+ fileMapping:
36
+ compilable: "compilable.c"
37
+ - name: "py"
38
+ readableName: "Python3"
39
+ extension: "py"
40
+ execution:
41
+ command: "python3 {executable}"
42
+ fileMapping:
43
+ executable: "executable.py"
44
+ extensions:
45
+ boca:
46
+ bocaLanguage: "py3"
47
+ - name: "java"
48
+ readableName: "Java"
49
+ extension: "java"
50
+ compilation:
51
+ commands:
52
+ - "javac -Xlint -encoding UTF-8 {compilable}"
53
+ - "jar cvf {executable} @glob:*.class"
54
+ execution:
55
+ command:
56
+ "java -Xss100m -Xmx{{memory}}m -Xms{{initialMemory}}m -cp {executable}
57
+ Main"
58
+ fileMapping:
59
+ compilable: "Main.java"
60
+ executable: "Main.jar"
61
+ extensions:
62
+ boca:
63
+ languages: ["c", "cc", "java", "py3"]
64
+ flags:
65
+ c: "-O2 -lm -static"
66
+ cc: "-std=c++20 -O2 -lm -static"
67
+ preferContestLetter: true
@@ -4,11 +4,15 @@ name: "default"
4
4
  uri: "rsalesc/rbx/rbx/resources/presets/default"
5
5
  problem: "problem"
6
6
  contest: "contest"
7
+ env: "env.rbx.yml"
7
8
  tracking:
8
9
  problem:
9
- - path: "statement/template.rbx.tex"
10
+ - path: ".gitignore"
10
11
  - path: "statement/icpc.sty"
11
- contest:
12
12
  - path: "statement/template.rbx.tex"
13
+ contest:
14
+ - path: ".gitignore"
13
15
  - path: "statement/icpc.sty"
16
+ - path: "statement/template.rbx.tex"
14
17
  - path: "statement/contest.rbx.tex"
18
+ symlink: true
@@ -3,4 +3,4 @@ build/
3
3
 
4
4
  *.o
5
5
  *.aux
6
- *.log
6
+ *.log
@@ -1,4 +1,14 @@
1
- %- if vars.show_problem is truthy
1
+ \documentclass[a4paper,11pt]{article}
2
+
3
+ \def\lang{\VAR{lang}}
4
+ \usepackage{icpc}
5
+
6
+ %- if problem.blocks.preamble is defined
7
+ \VAR{problem.blocks.preamble}
8
+ %- endif
9
+
10
+ \begin{document}
11
+
2
12
  \includeProblem
3
13
  %- if problem.short_name is defined
4
14
  [\VAR{problem.short_name}]
@@ -39,13 +49,9 @@
39
49
  %- endif
40
50
 
41
51
  %- if problem.blocks.notes is defined
42
- \subsection*{\strNotes}
52
+ \subsection*{Observações}
43
53
  \VAR{problem.blocks.notes}
44
54
  %- endif
45
55
  }
46
- %- endif
56
+ \end{document}
47
57
 
48
- %- if problem.blocks.editorial is nonnull and vars.editorial is truthy
49
- \subsection*{\strSolution}
50
- \VAR{problem.blocks.editorial}
51
- %- endif
@@ -3,6 +3,7 @@ from typing import Any
3
3
 
4
4
  import mechanize
5
5
 
6
+ from rbx import utils
6
7
  from rbx.console import console
7
8
  from rbx.schema import Problem
8
9
  from rbx.submitors.submitor import Submitor
@@ -55,7 +56,7 @@ class Session:
55
56
  )
56
57
 
57
58
  def submit_from_contest(self, url: str, file: pathlib.Path, typeid: int):
58
- filename = str(file.resolve())
59
+ filename = str(utils.abspath(file))
59
60
  self.br.open(url)
60
61
  form = self.select_form_by_class('submit-form', self.br.forms())
61
62
  if form is None:
@@ -67,7 +68,7 @@ class Session:
67
68
  self.br.submit()
68
69
 
69
70
  def submit(self, url: str, file: pathlib.Path, typeid: int):
70
- filename = str(file.resolve())
71
+ filename = str(utils.abspath(file))
71
72
  response = self.br.open(url)
72
73
  if response is None:
73
74
  raise Exception('Response was not received')
rbx/test.py CHANGED
@@ -159,7 +159,7 @@ def _pretty_print_outcome_panel(
159
159
  ) -> Panel:
160
160
  result: steps.CheckerResult = eval.result
161
161
  is_tle = result.outcome.is_slow() or (
162
- problem.timeLimit and eval.log.time * 1000 > problem.timeLimit
162
+ problem.timeLimit and (eval.log.time or 0) * 1000 > problem.timeLimit
163
163
  )
164
164
 
165
165
  text = Text()
rbx/utils.py CHANGED
@@ -3,6 +3,7 @@ import fcntl
3
3
  import functools
4
4
  import json
5
5
  import os
6
+ import os.path
6
7
  import pathlib
7
8
  import resource
8
9
  from typing import Any, Optional, Type, TypeVar
@@ -34,6 +35,10 @@ def highlight_str(s: str) -> text.Text:
34
35
  return txt
35
36
 
36
37
 
38
+ def abspath(path: pathlib.Path) -> pathlib.Path:
39
+ return pathlib.Path(os.path.abspath(path))
40
+
41
+
37
42
  def highlight_json_obj(obj: Any) -> text.Text:
38
43
  js = json.dumps(obj)
39
44
  return highlight_str(js)
@@ -70,7 +75,7 @@ def dump_schema(model: Type[BaseModel], path: pathlib.Path):
70
75
  def ensure_schema(model: Type[BaseModel]) -> pathlib.Path:
71
76
  path = get_app_path() / 'schemas' / f'{model.__name__}.json'
72
77
  dump_schema(model, path)
73
- return path.resolve()
78
+ return abspath(path)
74
79
 
75
80
 
76
81
  def model_json(model: BaseModel) -> str:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: rbx.cp
3
- Version: 0.8.0
3
+ Version: 0.9.0
4
4
  Summary:
5
5
  Author: Roberto Sales
6
6
  Requires-Python: >=3.9.1,<4.0.0
@@ -18,6 +18,7 @@ Requires-Dist: dateparser (>=1.2.1,<2.0.0)
18
18
  Requires-Dist: deepmerge (>=2.0,<3.0)
19
19
  Requires-Dist: fastapi (>=0.115.8,<0.116.0)
20
20
  Requires-Dist: filelock (>=3.14.0,<4.0.0)
21
+ Requires-Dist: gitignore-parser (>=0.1.12,<0.2.0)
21
22
  Requires-Dist: gitpython (>=3.1.43,<4.0.0)
22
23
  Requires-Dist: jinja2 (>=3.1.4,<4.0.0)
23
24
  Requires-Dist: lark (>=1.2.2,<2.0.0)