• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

ValeriyMenshikov / restcodegen / 18805103363

25 Oct 2025 03:38PM UTC coverage: 63.12% (-1.5%) from 64.627%
18805103363

push

github

web-flow
Merge pull request #7 from ValeriyMenshikov/release/issue-5

Closes #5
Closes #6

22 of 58 new or added lines in 9 files covered. (37.93%)

8 existing lines in 4 files now uncovered.

433 of 686 relevant lines covered (63.12%)

1.89 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/restcodegen/generator/rest_codegen.py
1
import json
×
NEW
2
from functools import cached_property
×
UNCOV
3
from pathlib import Path
×
4

5
from datamodel_code_generator import DataModelType, generate
×
6

7
from restcodegen.generator.base import BaseTemplateGenerator
×
8
from restcodegen.generator.log import LOGGER
×
9
from restcodegen.generator.parser import Parser
×
10
from restcodegen.generator.utils import (
×
11
    create_and_write_file,
12
    name_to_snake,
13
)
14

15

16
class RESTClientGenerator(BaseTemplateGenerator):
×
17
    BASE_PATH = Path(".") / "clients" / "http"
×
18

19
    def __init__(
×
20
        self,
21
        openapi_spec: Parser,
22
        templates_dir: str | None = None,
23
        async_mode: bool = False,
24
        base_path: str | Path | None = None,
25
    ) -> None:
26
        super().__init__(templates_dir=templates_dir)
×
27
        self.openapi_spec = openapi_spec
×
28
        self.async_mode = async_mode
×
NEW
29
        self.base_path = Path(base_path) if base_path is not None else self.BASE_PATH
×
30

NEW
31
    @cached_property
×
NEW
32
    def _base_import(self) -> str:
×
NEW
33
        base = self.base_path
×
NEW
34
        if base.is_absolute():
×
NEW
35
            try:
×
NEW
36
                base = base.relative_to(Path.cwd())
×
NEW
37
            except ValueError:
×
NEW
38
                pass
×
NEW
39
        return ".".join(list(base.parts))
×
40

41
    def generate(self) -> None:
×
42
        self._gen_clients()
×
43
        self._gen_init_apis()
×
44
        self._gen_models()
×
45

46
    def _gen_init_apis(self) -> None:
×
47
        LOGGER.info("Generate __init__.py for apis")
×
48
        rendered_code = self.env.get_template("apis_init.jinja2").render(
×
49
            api_names=self.openapi_spec.apis,
50
            service_name=self.openapi_spec.service_name,
51
            version=self.version,
52
            base_import=self._base_import,
53
        )
54
        file_name = f"{name_to_snake(self.openapi_spec.service_name)}/__init__.py"
×
NEW
55
        file_path = self.base_path / file_name
×
56
        create_and_write_file(file_path=file_path, text=rendered_code)
×
NEW
57
        create_and_write_file(file_path=file_path.parent.parent / "__init__.py", text="# coding: utf-8")
×
58

59
    def _gen_clients(self) -> None:
×
60
        for tag in self.openapi_spec.apis:
×
61
            LOGGER.info(f"Generate REST client for tag: {tag}")
×
62
            handlers = self.openapi_spec.handlers_by_tag(tag)
×
63
            models = self.openapi_spec.models_by_tag(tag)
×
64
            rendered_code = self.env.get_template("api_client.jinja2").render(
×
65
                async_mode=self.async_mode,
66
                models=models,
67
                data_list=handlers,
68
                api_name=tag,
69
                service_name=self.openapi_spec.service_name,
70
                version=self.version,
71
                base_import=self._base_import,
72
            )
73
            file_name = f"{name_to_snake(tag)}_api.py"
×
NEW
74
            file_path = self.base_path / name_to_snake(self.openapi_spec.service_name) / "apis" / file_name
×
UNCOV
75
            create_and_write_file(file_path=file_path, text=rendered_code)
×
NEW
76
            create_and_write_file(file_path=file_path.parent / "__init__.py", text="# coding: utf-8")
×
77

78
    def _gen_models(self) -> None:
×
79
        LOGGER.info(f"Generate models for service: {self.openapi_spec.service_name}")
×
NEW
80
        file_path = self.base_path / name_to_snake(self.openapi_spec.service_name) / "models" / "api_models.py"
×
UNCOV
81
        create_and_write_file(file_path=file_path)
×
NEW
82
        create_and_write_file(file_path=file_path.parent / "__init__.py", text="# coding: utf-8")
×
UNCOV
83
        header_path_template = self.templates_dir / "header.jinja2"
×
84
        generate(
×
85
            json.dumps(self.openapi_spec.openapi_spec),
86
            output=file_path,
87
            snake_case_field=True,
88
            output_model_type=DataModelType.PydanticV2BaseModel,
89
            reuse_model=True,
90
            field_constraints=True,
91
            custom_file_header_path=header_path_template,
92
            capitalise_enum_members=True,
93
            encoding="utf-8",
94
        )
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc