Skip to content
Merged
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
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ client-lint: client-setup-env ## Run linting checks for Polaris client
.PHONY: client-regenerate
client-regenerate: client-setup-env ## Regenerate the client code
@echo "--- Regenerating client code ---"
@$(ACTIVATE_AND_CD) && python3 generate_clients.py
@$(ACTIVATE_AND_CD) && python3 -B generate_clients.py
@echo "--- Client code regeneration complete ---"

.PHONY: client-unit-test
Expand Down
3 changes: 3 additions & 0 deletions client/python/.openapi-generator-ignore
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if we even need license generation -- and therefore this file -- anymore now that generated code isn't being checked into the repo.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's better to keep them as the plan is to publish them to the binary package.

Original file line number Diff line number Diff line change
Expand Up @@ -53,3 +53,6 @@ setup.cfg
tox.ini
README.md
pyproject.toml
docs/
**/catalog_README.md
**/management_README.md
Empty file removed client/python/docs/.keep
Empty file.
70 changes: 49 additions & 21 deletions client/python/generate_clients.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@
import subprocess
from pathlib import Path
import fnmatch
import logging
import argparse

# Paths
CLIENT_DIR = Path(__file__).parent
Expand Down Expand Up @@ -88,12 +90,14 @@
"gitignore",
]

logger = logging.getLogger(__name__)


def clean_old_tests() -> None:
print("Deleting old tests...")
logger.info("Deleting old tests...")
test_dir = CLIENT_DIR / "test"
if not test_dir.exists():
print(f"Test directory {test_dir} does not exist, skipping test cleanup.")
logger.info(f"Test directory {test_dir} does not exist, skipping test cleanup.")
return

for item in test_dir.rglob("*"):
Expand All @@ -103,20 +107,20 @@ def clean_old_tests() -> None:
if relative_path not in KEEP_TEST_FILES:
try:
os.remove(item)
print(f"{relative_path}: removed")
logger.debug(f"{relative_path}: removed")
except OSError as e:
print(f"Error removing {relative_path}: {e}")
logger.error(f"Error removing {relative_path}: {e}")
else:
print(f"{relative_path}: skipped")
logger.debug(f"{relative_path}: skipped")

init_py_to_delete = CLIENT_DIR / "test" / "__init__.py"
if init_py_to_delete.exists():
try:
os.remove(init_py_to_delete)
print(f"{init_py_to_delete.relative_to(CLIENT_DIR)}: removed")
logger.debug(f"{init_py_to_delete.relative_to(CLIENT_DIR)}: removed")
except OSError as e:
print(f"Error removing {init_py_to_delete.relative_to(CLIENT_DIR)}: {e}")
print("Old test deletion complete.")
logger.error(f"Error removing {init_py_to_delete.relative_to(CLIENT_DIR)}: {e}")
logger.info("Old test deletion complete.")


def generate_polaris_management_client() -> None:
Expand All @@ -133,12 +137,14 @@ def generate_polaris_management_client() -> None:
PACKAGE_NAME_POLARIS_MANAGEMENT,
"--additional-properties=apiNamePrefix=polaris",
PYTHON_VERSION,
"--additional-properties=generateSourceCodeOnly=true",
"--additional-properties=generateSourceCodeOnly=true",
"--skip-validate-spec",
"--ignore-file-override",
OPEN_API_GENERATOR_IGNORE,
"--global-property=apiDocs=false,modelDocs=false,modelTests=false,apiTests=false",
],
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
)


Expand All @@ -150,18 +156,20 @@ def generate_polaris_catalog_client() -> None:
"-i",
POLARIS_CATALOG_SPEC,
"-g",
"python",
"python",
"-o",
CLIENT_DIR,
PACKAGE_NAME_POLARIS_CATALOG,
"--additional-properties=apiNameSuffix=",
PYTHON_VERSION,
"--additional-properties=generateSourceCodeOnly=true",
"--additional-properties=generateSourceCodeOnly=true",
"--skip-validate-spec",
"--ignore-file-override",
OPEN_API_GENERATOR_IGNORE,
"--global-property=apiDocs=false,modelDocs=false,modelTests=false,apiTests=false",
],
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
)


Expand All @@ -173,19 +181,21 @@ def generate_iceberg_catalog_client() -> None:
"-i",
ICEBERG_CATALOG_SPEC,
"-g",
"python",
"python",
"-o",
CLIENT_DIR,
PACKAGE_NAME_POLARIS_CATALOG,
"--additional-properties=apiNameSuffix=",
"--additional-properties=apiNamePrefix=Iceberg",
PYTHON_VERSION,
"--additional-properties=generateSourceCodeOnly=true",
"--additional-properties=generateSourceCodeOnly=true",
"--skip-validate-spec",
"--ignore-file-override",
OPEN_API_GENERATOR_IGNORE,
"--global-property=apiDocs=false,modelDocs=false,modelTests=false,apiTests=false",
],
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
)


Expand All @@ -198,11 +208,11 @@ def _prepend_header_to_file(file_path: Path, header_file_path: Path) -> None:
f.seek(0)
f.write(header_content + original_content)
except IOError as e:
print(f"Error prepending header to {file_path}: {e}")
logger.error(f"Error prepending header to {file_path}: {e}")


def prepend_licenses() -> None:
print("Re-applying license headers...")
logger.info("Re-applying license headers...")
for file_path in CLIENT_DIR.rglob("*"):
if file_path.is_file():
relative_file_path = file_path.relative_to(CLIENT_DIR)
Expand All @@ -220,7 +230,7 @@ def prepend_licenses() -> None:

# Check if extension is excluded
if file_extension in EXCLUDE_EXTENSIONS:
print(f"{relative_file_path}: skipped (extension excluded)")
logger.debug(f"{relative_file_path}: skipped (extension excluded)")
continue

is_excluded = False
Expand All @@ -241,18 +251,18 @@ def prepend_licenses() -> None:
break

if is_excluded:
print(f"{relative_file_path}: skipped (path excluded)")
logger.debug(f"{relative_file_path}: skipped (path excluded)")
continue

header_file_path = HEADER_DIR / f"header-{file_extension}.txt"

if header_file_path.is_file():
_prepend_header_to_file(file_path, header_file_path)
print(f"{relative_file_path}: updated")
logger.debug(f"{relative_file_path}: updated")
else:
print(f"No header compatible with file {relative_file_path}")
logger.error(f"No header compatible with file {relative_file_path}")
sys.exit(2)
print("License fix complete.")
logger.info("License fix complete.")


def build() -> None:
Expand All @@ -263,5 +273,23 @@ def build() -> None:
prepend_licenses()


if __name__ == "__main__":
def main():
parser = argparse.ArgumentParser(description="Generate Polaris Python clients.")
parser.add_argument(
"-v",
"--verbose",
action="store_true",
help="Enable verbose output for debugging.",
)
args = parser.parse_args()

if args.verbose:
logging.basicConfig(level=logging.DEBUG, format="%(message)s")
else:
logging.basicConfig(level=logging.INFO, format="%(message)s")

build()


if __name__ == "__main__":
main()