Skip to content

Commit d8ae979

Browse files
authored
Merge pull request #226 from jdkandersson/enhancement/keep-more-info-in-build
Enhancement/keep more info in build
2 parents 2bdad18 + 9de3754 commit d8ae979

3 files changed

Lines changed: 282 additions & 93 deletions

File tree

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
### Added
11+
12+
- Add version, title and description (if defined) into the JSON OpenAPI
13+
specification stored with the package generated by the build module.
14+
1015
## [v2.0.0] - 2020-11-15
1116

1217
### Added

open_alchemy/build/__init__.py

Lines changed: 104 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
"""Build a package with the OpenAlchemy models."""
22

3+
import dataclasses
34
import enum
45
import hashlib
56
import json
@@ -92,21 +93,44 @@ def get_schemas(*, spec: typing.Any) -> types.Schemas:
9293
return schemas
9394

9495

95-
def generate_spec(*, schemas: types.Schemas) -> str:
96+
TVersion = str
97+
TTitle = typing.Optional[str]
98+
TDescription = typing.Optional[str]
99+
TSpecStr = str
100+
101+
102+
def generate_spec_str(
103+
*,
104+
schemas: types.Schemas,
105+
version: TVersion,
106+
title: TTitle,
107+
description: TDescription,
108+
) -> TSpecStr:
96109
"""
97-
Generate the spec.json file contents.
110+
Generate a string representation of the spec.
98111
99112
Args:
100-
schemas: The schemas to generate the spec for.
113+
schemas: The schemas of the spec.
114+
version: The version of the spec.
115+
title: The title of the spec.
116+
description: The description of the spec.
101117
102118
Returns:
103119
The JSON encoded schemas.
104120
105121
"""
106-
return json.dumps({"components": {"schemas": schemas}}, separators=(",", ":"))
122+
info = {"version": version}
123+
if title is not None:
124+
info["title"] = title
125+
if description is not None:
126+
info["description"] = description
127+
128+
return json.dumps(
129+
{"info": info, "components": {"schemas": schemas}}, separators=(",", ":")
130+
)
107131

108132

109-
def calculate_version(*, spec: typing.Any, spec_str: str) -> str:
133+
def calculate_version(*, spec: typing.Any, schemas: types.Schemas) -> TVersion:
110134
"""
111135
Calculate the version for a spec.
112136
@@ -124,15 +148,68 @@ def calculate_version(*, spec: typing.Any, spec_str: str) -> str:
124148
"""
125149
try:
126150
spec_version = spec["info"]["version"]
127-
if isinstance(spec_version, str):
151+
if isinstance(spec_version, TVersion):
128152
return spec_version
129153
except (KeyError, TypeError):
130154
pass
131155

156+
spec_str = json.dumps({"components": {"schemas": schemas}}, separators=(",", ":"))
132157
return hashlib.sha1(spec_str.encode()).hexdigest()[:20]
133158

134159

135-
def generate_setup(*, name: str, version: str) -> str:
160+
@dataclasses.dataclass
161+
class TSpecInfo:
162+
"""
163+
Information about the spec.
164+
165+
Attrs:
166+
version: Unique identifier for this instance.
167+
spec_str: The string representation.
168+
title: A name describing the spec.
169+
description: More detailed summary of the spec.
170+
171+
"""
172+
173+
version: TVersion
174+
spec_str: TSpecStr
175+
title: TTitle
176+
description: TDescription
177+
178+
179+
def calculate_spec_info(*, schemas: types.Schemas, spec: typing.Any) -> TSpecInfo:
180+
"""
181+
Calculate information about the spec.
182+
183+
Args:
184+
schemas: The schemas from the spec.
185+
spec: The spec as a dictionary.
186+
187+
Returns:
188+
The spec string to be stored, the version, and the title and description (if
189+
they are defined).
190+
191+
"""
192+
version = calculate_version(spec=spec, schemas=schemas)
193+
194+
title: TTitle = None
195+
description: TDescription = None
196+
if "info" in spec:
197+
title = spec["info"].get("title")
198+
description = spec["info"].get("description")
199+
200+
spec_str = generate_spec_str(
201+
schemas=schemas, version=version, title=title, description=description
202+
)
203+
204+
return TSpecInfo(
205+
version=version, spec_str=spec_str, title=title, description=description
206+
)
207+
208+
209+
TName = str
210+
211+
212+
def generate_setup(*, name: TName, version: TVersion) -> str:
136213
"""
137214
Generate the content of the setup.py file.
138215
@@ -152,7 +229,7 @@ def generate_setup(*, name: str, version: str) -> str:
152229
)
153230

154231

155-
def generate_manifest(*, name: str) -> str:
232+
def generate_manifest(*, name: TName) -> str:
156233
"""
157234
Generate the content of the MANIFEST.in file.
158235
@@ -221,8 +298,17 @@ def generate_init(open_alchemy: str, models_file: str) -> str:
221298
)
222299

223300

301+
TPath = str
302+
303+
224304
def dump(
225-
*, path: str, name: str, setup: str, manifest: str, spec: str, init: str
305+
*,
306+
path: TPath,
307+
name: TName,
308+
setup: str,
309+
manifest: str,
310+
spec_str: TSpecStr,
311+
init: str,
226312
) -> None:
227313
"""
228314
Dump the files needed for the package at a path.
@@ -246,13 +332,13 @@ def dump(
246332
# Write files in the package directory.
247333
package = directory / name
248334
package.mkdir(parents=True, exist_ok=True)
249-
(package / "spec.json").write_text(spec)
335+
(package / "spec.json").write_text(spec_str)
250336
(package / "__init__.py").write_text(init)
251337
except OSError as exc:
252338
raise exceptions.BuildError(str(exc)) from exc
253339

254340

255-
def build_dist(name: str, path: str, format_: PackageFormat) -> None:
341+
def build_dist(name: TName, path: TPath, format_: PackageFormat) -> None:
256342
"""
257343
Build a distribution package.
258344
@@ -273,7 +359,7 @@ def build_dist(name: str, path: str, format_: PackageFormat) -> None:
273359
build_wheel(name, path)
274360

275361

276-
def build_sdist(name: str, path: str) -> None:
362+
def build_sdist(name: TName, path: TPath) -> None:
277363
"""
278364
Build a .tar.gz source distribution and place it in a "dist" folder.
279365
@@ -286,7 +372,7 @@ def build_sdist(name: str, path: str) -> None:
286372
helpers.command.run([sys.executable, "setup.py", "sdist"], str(pkg_dir))
287373

288374

289-
def build_wheel(name: str, path: str) -> None:
375+
def build_wheel(name: TName, path: TPath) -> None:
290376
"""
291377
Build a .whl package and place it in a "dist" folder.
292378
@@ -308,8 +394,8 @@ def build_wheel(name: str, path: str) -> None:
308394
def execute(
309395
*,
310396
spec: typing.Any,
311-
name: str,
312-
path: str,
397+
name: TName,
398+
path: TPath,
313399
format_: PackageFormat,
314400
) -> None:
315401
"""
@@ -324,9 +410,8 @@ def execute(
324410
"""
325411
validate_dist_format(format_)
326412
schemas = get_schemas(spec=spec)
327-
spec_str = generate_spec(schemas=schemas)
328-
version = calculate_version(spec=spec, spec_str=spec_str)
329-
setup = generate_setup(name=name, version=version)
413+
spec_info = calculate_spec_info(schemas=schemas, spec=spec)
414+
setup = generate_setup(name=name, version=spec_info.version)
330415
manifest = generate_manifest(name=name)
331416

332417
init_open_alchemy = generate_init_open_alchemy()
@@ -338,7 +423,7 @@ def execute(
338423
name=name,
339424
setup=setup,
340425
manifest=manifest,
341-
spec=spec_str,
426+
spec_str=spec_info.spec_str,
342427
init=init,
343428
)
344429

0 commit comments

Comments
 (0)