Skip to content

Commit 07a2c2b

Browse files
♻️ Make code synchronous.
1 parent e5acfa3 commit 07a2c2b

File tree

10 files changed

+126
-137
lines changed

10 files changed

+126
-137
lines changed

poetry.lock

Lines changed: 16 additions & 18 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ packages = [{ include = "lapidary", from = "src" }]
3333

3434
[tool.poetry.dependencies]
3535
python = "^3.13"
36-
asyncclick = "^8"
36+
click = "^8"
3737
httpx = "^0.28"
3838
libcst = "^1.5"
3939
openapi-pydantic = "^0.5"

src/lapidary/render/cli.py

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
import sys
22
from pathlib import Path
33

4-
import anyio
5-
import asyncclick as click
4+
import click
65

76

87
@click.group()
@@ -18,12 +17,12 @@ def app(verbose: bool) -> None:
1817

1918
@app.command()
2019
@click.argument('document')
21-
@click.argument('project_root')
20+
@click.argument('project_root', type=click.Path(path_type=Path, exists=False, file_okay=False, dir_okay=True))
2221
@click.argument('package_name')
2322
@click.option('--save/--no-save', help='Copy the document in the project', default=False)
24-
async def init(
23+
def init(
2524
document: str,
26-
project_root: str,
25+
project_root: Path,
2726
package_name: str,
2827
save: bool = False,
2928
):
@@ -39,29 +38,33 @@ async def init(
3938
from .main import init_project
4039

4140
try:
42-
await init_project(document, anyio.Path(project_root), package_name, save)
41+
init_project(document, project_root, package_name, save)
4342
except FileExistsError:
4443
raise click.ClickException('Target exists')
4544

4645

4746
@app.command()
48-
@click.argument('project_root', type=click.Path(exists=True, file_okay=False, dir_okay=True), default='.')
49-
async def render(
47+
@click.argument(
48+
'project_root', type=click.Path(path_type=Path, exists=True, file_okay=False, dir_okay=True), default='.'
49+
)
50+
def render(
5051
project_root: Path = Path(),
5152
) -> None:
5253
"""Generate Python code"""
5354
from .main import render_project
5455

55-
await render_project(anyio.Path(project_root))
56+
render_project(project_root)
5657

5758

5859
@app.command(hidden=True)
59-
@click.argument('project_root', type=click.Path(exists=True, file_okay=False, dir_okay=True), default='.')
60+
@click.argument(
61+
'project_root', type=click.Path(path_type=Path, exists=True, file_okay=False, dir_okay=True), default='.'
62+
)
6063
@click.option('--process', is_flag=True, help='Output processed python model', default=False)
61-
async def dump_model(
64+
def dump_model(
6265
project_root: Path = Path(),
6366
process: bool = False,
6467
) -> None:
6568
from .main import dump_model as dump_model_
6669

67-
await dump_model_(anyio.Path(project_root), process, sys.stdout)
70+
dump_model_(project_root, process, sys.stdout)

src/lapidary/render/config.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,21 @@
11
import tomllib
2-
from collections.abc import Sequence
2+
from pathlib import Path
33

4-
import anyio
54
import pydantic
65

76
PYPROJ_TOML = 'pyproject.toml'
87

98

109
class Config(pydantic.BaseModel):
11-
document_path: str | None = None
10+
document_path: str
1211
"""URL or path relative to ./openapi/"""
1312
origin: pydantic.AnyHttpUrl | None = None
1413
"""Origin URL in case"""
1514
package: str
1615

1716

18-
async def load_config(project_root: anyio.Path) -> Config:
19-
text = await (project_root / PYPROJ_TOML).read_text()
17+
def load_config(project_root: Path) -> Config:
18+
text = (project_root / PYPROJ_TOML).read_text()
2019
pyproj = tomllib.loads(text)
2120
pyproj_dict = pyproj['tool']['lapidary']
2221
return Config.model_validate(pyproj_dict)

src/lapidary/render/load.py

Lines changed: 28 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import abc
22
import logging
33
from collections.abc import Mapping
4+
from pathlib import Path
45

5-
import anyio
66
import httpx
77
import ruamel.yaml
88

@@ -11,21 +11,21 @@
1111
logger = logging.getLogger(__name__)
1212

1313

14-
async def load_document(root: anyio.Path, config: Config) -> Mapping:
14+
def load_document(root: Path, config: Config) -> Mapping:
1515
logger.info('Load OpenAPI document')
1616

1717
yaml = ruamel.yaml.YAML(typ='safe')
1818

19-
text = await document_handler_for(root, config.document_path).load()
19+
text = document_handler_for(root, config.document_path).load()
2020
return yaml.load(text)
2121

2222

23-
class DocumentHandler[P: str | anyio.Path](abc.ABC):
24-
def __init__(self, path: P) -> None:
23+
class DocumentHandler(abc.ABC):
24+
def __init__(self, path: str) -> None:
2525
self._path = path
2626

2727
@abc.abstractmethod
28-
async def load(self) -> str:
28+
def load(self) -> str:
2929
"""Return document text and, which could be URL path or local file path."""
3030

3131
@property
@@ -38,42 +38,42 @@ def path(self) -> str:
3838
return str(self._path)
3939

4040
@abc.abstractmethod
41-
async def save_to(self, target: anyio.Path) -> str:
41+
def save_to(self, target: Path) -> str:
4242
"""Save the document.
4343
:param target: target directory
4444
:return: file name of the saved document"""
4545

4646

47-
class FileDocumentHandler(DocumentHandler[anyio.Path]):
48-
def __init__(self, project_root: anyio.Path, path: anyio.Path) -> None:
49-
assert isinstance(project_root, anyio.Path)
50-
assert isinstance(path, anyio.Path)
47+
class FileDocumentHandler(DocumentHandler):
48+
def __init__(self, project_root: Path, path: str) -> None:
49+
assert isinstance(project_root, Path)
5150
super().__init__(path)
5251
self._project_root = project_root
5352

54-
async def load(self) -> str:
55-
return await (self._project_root / self._path).read_text()
53+
def load(self) -> str:
54+
return (self._project_root / self._path).read_text()
5655

57-
async def save_to(self, target: anyio.Path) -> str:
56+
def save_to(self, target: Path) -> str:
5857
import shutil
5958

60-
shutil.copyfile(self._path, target / self._path.name)
61-
return self._path.name
59+
src_path = Path(self._path)
60+
shutil.copyfile(self._path, target / src_path.name)
61+
return src_path.name
6262

6363
@property
6464
def is_url(self) -> bool:
6565
return False
6666

6767

68-
class HttpDocumentHandler(DocumentHandler[str]):
68+
class HttpDocumentHandler(DocumentHandler):
6969
def __init__(self, path: str) -> None:
7070
super().__init__(path)
71-
self._client = httpx.AsyncClient(timeout=30.0)
71+
self._client = httpx.Client(timeout=30.0)
7272
self._cache: str | None = None
7373

74-
async def load(self) -> str:
74+
def load(self) -> str:
7575
if not self._cache:
76-
response = await self._client.get(self._path)
76+
response = self._client.get(self._path)
7777
self._cache = response.text
7878
assert self._cache is not None
7979
return self._cache
@@ -86,20 +86,19 @@ def _file_name(self) -> str:
8686
_, name = split(parsed.path)
8787
return name or 'openapi.yaml'
8888

89-
async def save_to(self, target: anyio.Path) -> str:
90-
text = await self.load()
89+
def save_to(self, target: Path) -> str:
90+
text = self.load()
9191
file_name = self._file_name()
92-
await (target / file_name).write_text(text)
92+
(target / file_name).write_text(text)
9393
return file_name
9494

9595
@property
9696
def is_url(self) -> bool:
9797
return True
9898

9999

100-
def document_handler_for(document_root: anyio.Path, path: str | anyio.Path) -> DocumentHandler:
101-
match path:
102-
case str() if path.startswith(('http://', 'https://')):
103-
return HttpDocumentHandler(path)
104-
case _:
105-
return FileDocumentHandler(document_root, anyio.Path(path))
100+
def document_handler_for(document_root: Path, path: str) -> DocumentHandler:
101+
if path.startswith(('http://', 'https://')):
102+
return HttpDocumentHandler(path)
103+
else:
104+
return FileDocumentHandler(document_root, str(path))

src/lapidary/render/main.py

Lines changed: 20 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
import logging
2-
import pathlib
32
from collections.abc import Mapping
3+
from pathlib import Path, PurePath
44
from typing import TextIO
55

6-
import anyio
7-
import asyncclick as click
6+
import click
87
import pydantic
98
import ruamel.yaml
109

@@ -15,38 +14,38 @@
1514
logger = logging.getLogger(__name__)
1615

1716

18-
async def init_project(
17+
def init_project(
1918
document_path: str,
20-
project_root: anyio.Path,
19+
project_root: Path,
2120
package_name: str,
2221
save_document: bool,
2322
) -> None:
2423
"""Create project directory and pyproject file, download or copy the OpenAPI document"""
2524

26-
if await project_root.exists():
25+
if project_root.exists():
2726
raise FileExistsError
2827

2928
from .writer import init_project
3029

31-
document_handler = document_handler_for(anyio.Path(), document_path)
30+
document_handler = document_handler_for(Path(), document_path)
3231

3332
if save_document:
34-
document_root = anyio.Path('lapidary/openapi')
33+
document_root = Path('lapidary/openapi')
3534
target_dir = project_root / document_root
36-
await target_dir.mkdir(parents=True)
37-
file_name = await document_handler.save_to(target_dir)
35+
target_dir.mkdir(parents=True)
36+
file_name = document_handler.save_to(target_dir)
3837
config_document_path = str(document_root / file_name)
3938
else:
4039
logger.warning('Saving OpenAPI document is recommended for portable and repeatable builds')
4140
if not document_handler.is_url:
42-
document_path_path = pathlib.PurePath(document_path)
41+
document_path_path = PurePath(document_path)
4342
if not document_path_path.is_absolute():
4443
# document path is a file outside of the project root.
4544
# If it's relative, make it relative to the project root.
4645
try:
4746
config_document_path = str(document_path_path.relative_to(project_root, walk_up=True))
4847
except ValueError:
49-
config_document_path = str(await anyio.Path.cwd() / document_path_path)
48+
config_document_path = str(Path.cwd() / document_path_path)
5049
else:
5150
config_document_path = document_path
5251
else:
@@ -60,18 +59,18 @@ async def init_project(
6059
)
6160

6261
yaml = ruamel.yaml.YAML(typ='safe')
63-
document = yaml.load(await document_handler.load())
62+
document = yaml.load(document_handler.load())
6463

65-
await init_project(project_root, config, document)
64+
init_project(project_root, config, document)
6665

6766

68-
async def render_project(project_root: anyio.Path) -> None:
67+
def render_project(project_root: Path) -> None:
6968
from .writer import update_project
7069

71-
config = await load_config(project_root)
70+
config = load_config(project_root)
7271

7372
logger.info('Parse OpenAPI document')
74-
oa_doc = await load_document(project_root, config)
73+
oa_doc = load_document(project_root, config)
7574
model = prepare_python_model(oa_doc, config)
7675

7776
logger.info('Render project')
@@ -85,17 +84,17 @@ async def render_project(project_root: anyio.Path) -> None:
8584
def progress(module: python.AbstractModule) -> None:
8685
progressbar.update(1, module)
8786

88-
await update_project(
87+
update_project(
8988
model.modules,
9089
project_root / 'src',
9190
config.package,
9291
progress,
9392
)
9493

9594

96-
async def dump_model(project_root: anyio.Path, process: bool, output: TextIO):
97-
config = await load_config(project_root)
98-
oa_doc = await load_document(project_root, config)
95+
def dump_model(project_root: Path, process: bool, output: TextIO):
96+
config = load_config(project_root)
97+
oa_doc = load_document(project_root, config)
9998
yaml = ruamel.yaml.YAML(typ='safe')
10099

101100
if not process:

0 commit comments

Comments
 (0)