Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
The diff you're trying to view is too large. We only load the first 3000 changed files.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ Then, enjoy githubkit now!

```python
from githubkit import Response
from githubkit.versions.latest.models import FullRepository
from githubkit_schemas.latest.models import FullRepository

resp: Response[FullRepository] = github.rest.repos.get("owner", "repo")
repo: FullRepository = resp.parsed_data
Expand Down
105 changes: 51 additions & 54 deletions codegen/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -205,80 +205,76 @@ def build_latest_version(
logger.info("Successfully generated latest version!")


def build_legacy_rest_models(
file: Path, output_module: str, latest_version_module: str, model_names: list[str]
def build_core(
dir: Path, output_module: str, versions: dict[str, str], latest_version: str
):
logger.info("Start generating legacy rest models...")
models_template = env.get_template("latest/models.py.jinja")
file.write_text(
models_template.render(
output_module=output_module,
latest_version_module=latest_version_module,
model_names=model_names,
)
)
logger.info("Successfully generated legacy rest models!")


def build_versions(dir: Path, versions: dict[str, str], latest_version: str):
logger.info("Start generating versions...")
logger.info("Start generating core...")

# build __init__.py
logger.info("Building versions __init__.py...")
init_template = env.get_template("versions/__init__.py.jinja")
logger.info("Building core __init__.py...")
init_template = env.get_template("core/__init__.py.jinja")
init_path = dir / "__init__.py"
init_path.write_text(
init_template.render(versions=versions, latest_version=latest_version)
init_template.render(
output_module=output_module,
versions=versions,
latest_version=latest_version,
)
)

# build rest.py
logger.info("Building versions rest.py...")
rest_template = env.get_template("versions/rest.py.jinja")
logger.info("Building core rest.py...")
rest_template = env.get_template("core/rest.py.jinja")
rest_path = dir / "rest.py"
rest_path.write_text(
rest_template.render(versions=versions, latest_version=latest_version)
rest_template.render(
output_module=output_module,
versions=versions,
latest_version=latest_version,
)
)

# build webhooks.py
logger.info("Building versions webhooks.py...")
webhooks_template = env.get_template("versions/webhooks.py.jinja")
logger.info("Building core webhooks.py...")
webhooks_template = env.get_template("core/webhooks.py.jinja")
webhooks_path = dir / "webhooks.py"
webhooks_path.write_text(
webhooks_template.render(versions=versions, latest_version=latest_version)
webhooks_template.render(
output_module=output_module,
versions=versions,
latest_version=latest_version,
)
)

logger.info("Successfully generated versions!")
logger.info("Successfully generated core!")


def build_lock_file(file: Path, lock_data: tomlkit.TOMLDocument):
file.write_text(lock_data.as_string())
logger.info("Successfully generated lock file!")


def build():
config = load_config()
logger.info(f"Loaded config: {config!r}")

# clean output dir
if config.output_dir.exists():
logger.warning(f"Output dir {config.output_dir} already exists, deleting...")
shutil.rmtree(config.output_dir)
config.output_dir.mkdir(parents=True, exist_ok=True)
# clean legacy rest models
if config.legacy_rest_models.exists():
logger.warning(
f"Legacy rest models {config.legacy_rest_models} "
"already exists, deleting..."
)
config.legacy_rest_models.unlink()

output_module = ".".join(config.output_dir.parts)
versions: dict[str, str] = {}
latest_version: str | None = None
latest_model_names: list[str] = []
latest_event_names: list[str] = []

for description in config.descriptions:
logger.info(f"Start getting OpenAPI source for {description.identifier}...")

version_path = description.output_dir / description.module
if version_path.exists():
logger.warning(
f"Description {description.identifier} "
f"output path {version_path} already exists, deleting..."
)
shutil.rmtree(version_path)
version_path.mkdir(parents=True, exist_ok=True)

source = get_source(description.source)
description._actual_source = str(source.uri.copy_with(fragment=None))
logger.info(f"Getting schema from {source.uri} succeeded!")
Expand Down Expand Up @@ -306,9 +302,6 @@ def build():
latest_model_names = [model.class_name for model in parsed_data.models]
latest_event_names = list(parsed_data.webhooks_by_event.keys())

version_path = config.output_dir / description.module
version_path.mkdir(parents=True, exist_ok=True)

# generate __init__.py
init_template = env.get_template("__init__.py.jinja")
init_path = version_path / "__init__.py"
Expand Down Expand Up @@ -340,20 +333,24 @@ def build():
if latest_version is None:
raise RuntimeError("No latest version found!")

latest_path = config.output_dir / "latest"
latest_path.mkdir(parents=True, exist_ok=True)
latest_path = config.schemas_output_dir / "latest"
if latest_path.exists():
logger.warning(f"Latest version path {latest_path} already exists, deleting...")
shutil.rmtree(latest_path)
latest_path.mkdir(parents=True, exist_ok=True)
build_latest_version(
latest_path,
output_module,
config.schemas_output_dir.name,
versions[latest_version],
latest_model_names,
latest_event_names,
)
build_versions(config.output_dir, versions, latest_version)
build_legacy_rest_models(
config.legacy_rest_models,
output_module,
versions[latest_version],
latest_model_names,
)
build_lock_file(config.output_dir / LOCK_FILE_NAME, config.to_lock())

core_path = config.schemas_output_dir / "core"
if core_path.exists():
logger.warning(f"Schema core path {core_path} already exists, deleting...")
shutil.rmtree(core_path)
core_path.mkdir(parents=True, exist_ok=True)
build_core(core_path, config.schemas_output_dir.name, versions, latest_version)

build_lock_file(config.schemas_output_dir / LOCK_FILE_NAME, config.to_lock())
5 changes: 3 additions & 2 deletions codegen/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ class DescriptionConfig(BaseModel):
"""If true, the description will be used as the default description."""
source: str
"""Source link to the description file."""
output_dir: Path
"""Output dir for the description file."""

_actual_source: str | None = None
"""The actual source link after downloading, if applicable."""
Expand Down Expand Up @@ -121,5 +123,4 @@ def to_lock(self) -> TOMLDocument:


class Config(GenerationInfo):
output_dir: Path
legacy_rest_models: Path
schemas_output_dir: Path
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ from . import VERSIONS, LATEST_VERSION, VERSION_TYPE
if TYPE_CHECKING:
from githubkit import GitHubCore, Response
{% for version, module in versions.items() %}
from .{{ module }}.rest import RestNamespace as {{ pascal_case(module) }}RestNamespace
from {{ output_module }}.{{ module }}.rest import RestNamespace as {{ pascal_case(module) }}RestNamespace
{% endfor %}


Expand Down Expand Up @@ -101,7 +101,20 @@ class RestVersionSwitcher(_VersionProxy):
cache = self._cached_namespaces.setdefault(g, {})
if version in cache:
return cache[version]
module = importlib.import_module(f".{VERSIONS[version]}.rest", __package__)

if version not in VERSIONS:
raise ValueError(
f"Version {version!r} is not a valid version. "
f"Valid versions are: {', '.join(VERSIONS.keys())}"
)

try:
module = importlib.import_module(f"{{ output_module }}.{VERSIONS[version]}.rest")
except ModuleNotFoundError:
raise RuntimeError(
f"Version {version!r} is not installed. "
f"Please install it via 'pip install githubkit-schemas[{version}]'"
)
namespace = module.RestNamespace(g)
cache[version] = namespace
return namespace
64 changes: 64 additions & 0 deletions codegen/templates/core/webhooks.py.jinja
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
{% from "header.jinja" import header %}

"""{{ header() }}"""

import importlib
from typing import TYPE_CHECKING, Any, Literal, ClassVar, overload

from . import VERSIONS, LATEST_VERSION, VERSION_TYPE

if TYPE_CHECKING:
{% for version, module in versions.items() %}
from {{ output_module }}.{{ module }}.webhooks import WebhookNamespace as {{ pascal_case(module) }}WebhookNamespace
{% endfor %}

if TYPE_CHECKING:

class _VersionProxy({{ pascal_case(versions[latest_version]) }}WebhookNamespace):
...

else:
_VersionProxy = object

class WebhooksVersionSwitcher(_VersionProxy):
_cached_namespaces: ClassVar[dict[VERSION_TYPE, Any]] = {}

if not TYPE_CHECKING:
def __getattr__(self, name: str) -> Any:
if name.startswith("_"):
raise AttributeError(
f"'{self.__class__.__name__}' object has no attribute '{name}'"
)
namespace = self()
return getattr(namespace, name)

{% for version, module in versions.items() %}
@overload
def __call__(self, version: Literal["{{ version }}"]) -> "{{ pascal_case(module) }}WebhookNamespace":
...
{% endfor %}

@overload
def __call__(self) -> "{{ pascal_case(versions[latest_version]) }}WebhookNamespace":
...

def __call__(self, version: VERSION_TYPE = LATEST_VERSION) -> Any:
if version in self._cached_namespaces:
return self._cached_namespaces[version]

if version not in VERSIONS:
raise ValueError(
f"Version {version!r} is not a valid version. "
f"Valid versions are: {', '.join(VERSIONS.keys())}"
)

try:
module = importlib.import_module(f"{{ output_module }}.{VERSIONS[version]}.webhooks")
except ModuleNotFoundError:
raise RuntimeError(
f"Version {version!r} is not installed. "
f"Please install it via 'pip install githubkit-schemas[{version}]'"
)
namespace = module.WebhookNamespace()
self._cached_namespaces[version] = namespace
return namespace
2 changes: 1 addition & 1 deletion codegen/templates/latest/models.py.jinja
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

from typing import TYPE_CHECKING

from githubkit.lazy_module import is_lazy_disabled
from githubkit.module_hooks.lazy_module import is_lazy_disabled

if TYPE_CHECKING or is_lazy_disabled():
{% for name in model_names %}
Expand Down
2 changes: 1 addition & 1 deletion codegen/templates/latest/types.py.jinja
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

from typing import TYPE_CHECKING

from githubkit.lazy_module import is_lazy_disabled
from githubkit.module_hooks.lazy_module import is_lazy_disabled

if TYPE_CHECKING or is_lazy_disabled():
{% for name in model_names %}
Expand Down
2 changes: 1 addition & 1 deletion codegen/templates/latest/webhooks.py.jinja
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

from typing import TYPE_CHECKING

from githubkit.lazy_module import is_lazy_disabled
from githubkit.module_hooks.lazy_module import is_lazy_disabled

if TYPE_CHECKING or is_lazy_disabled():
{% for name in event_names %}
Expand Down
2 changes: 1 addition & 1 deletion codegen/templates/models/models.py.jinja
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

from typing import TYPE_CHECKING

from githubkit.lazy_module import is_lazy_disabled
from githubkit.module_hooks.lazy_module import is_lazy_disabled

if TYPE_CHECKING or is_lazy_disabled():
{% for group in groups %}
Expand Down
2 changes: 1 addition & 1 deletion codegen/templates/models/types.py.jinja
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

from typing import TYPE_CHECKING

from githubkit.lazy_module import is_lazy_disabled
from githubkit.module_hooks.lazy_module import is_lazy_disabled

if TYPE_CHECKING or is_lazy_disabled():
{% for group in groups %}
Expand Down
51 changes: 0 additions & 51 deletions codegen/templates/versions/webhooks.py.jinja

This file was deleted.

2 changes: 1 addition & 1 deletion codegen/templates/webhooks/__init__.py.jinja
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

from typing import TYPE_CHECKING

from githubkit.lazy_module import is_lazy_disabled
from githubkit.module_hooks.lazy_module import is_lazy_disabled

if TYPE_CHECKING or is_lazy_disabled():
{% for name in event_names %}
Expand Down
Loading
Loading