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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ request adding CHANGELOG notes for breaking (!) changes and possibly other secti
- `client.region` is no longer considered a "credential" property (related to Iceberg REST Catalog API).
- Relaxed the requirements for S3 storage's ARN to allow Polaris to connect to more non-AWS S3 storage appliances.
- Added checksum to helm deployment so that it will restart when the configmap has changed.
- Added Windows support for Python client

### Deprecations

Expand Down
130 changes: 61 additions & 69 deletions client/python/generate_clients.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,12 @@

# Paths
CLIENT_DIR = Path(__file__).parent
HEADER_DIR = os.path.join(CLIENT_DIR, "templates")
SPEC_DIR = os.path.join(CLIENT_DIR, "spec")
POLARIS_MANAGEMENT_SPEC = os.path.join(SPEC_DIR, "polaris-management-service.yml")
ICEBERG_CATALOG_SPEC = os.path.join(SPEC_DIR, "iceberg-rest-catalog-open-api.yaml")
POLARIS_CATALOG_SPEC = os.path.join(SPEC_DIR, "polaris-catalog-service.yaml")
OPEN_API_GENERATOR_IGNORE = os.path.join(CLIENT_DIR, ".openapi-generator-ignore")
HEADER_DIR = CLIENT_DIR / "templates"
SPEC_DIR = CLIENT_DIR / "spec"
POLARIS_MANAGEMENT_SPEC = SPEC_DIR / "polaris-management-service.yml"
ICEBERG_CATALOG_SPEC = SPEC_DIR / "iceberg-rest-catalog-open-api.yaml"
POLARIS_CATALOG_SPEC = SPEC_DIR / "polaris-catalog-service.yaml"
OPEN_API_GENERATOR_IGNORE = CLIENT_DIR / ".openapi-generator-ignore"

# Open API Generator Configs
PACKAGE_NAME_POLARIS_MANAGEMENT = (
Expand All @@ -58,20 +58,20 @@
]
EXCLUDE_PATHS = [
Path(".gitignore"),
Path(".openapi-generator/"),
Path(".openapi-generator"),
Path(".openapi-generator-ignore"),
Path(".pytest_cache/"),
Path(".pytest_cache"),
Path("test/test_cli_parsing.py"),
Path("apache_polaris/__pycache__/"),
Path("apache_polaris/cli/"),
Path("apache_polaris/sdk/__pycache__/"),
Path("apache_polaris/sdk/catalog/__pycache__/"),
Path("apache_polaris/sdk/catalog/models/__pycache__/"),
Path("apache_polaris/sdk/catalog/api/__pycache__/"),
Path("apache_polaris/sdk/management/__pycache__/"),
Path("apache_polaris/sdk/management/models/__pycache__/"),
Path("apache_polaris/sdk/management/api/__pycache__/"),
Path("integration_tests/"),
Path("apache_polaris/__pycache__"),
Path("apache_polaris/cli"),
Path("apache_polaris/sdk/__pycache__"),
Path("apache_polaris/sdk/catalog/__pycache__"),
Path("apache_polaris/sdk/catalog/models/__pycache__"),
Path("apache_polaris/sdk/catalog/api/__pycache__"),
Path("apache_polaris/sdk/management/__pycache__"),
Path("apache_polaris/sdk/management/models/__pycache__"),
Path("apache_polaris/sdk/management/api/__pycache__"),
Path("integration_tests"),
Path(".github/workflows/python.yml"),
Path(".gitlab-ci.yml"),
Path("pyproject.toml"),
Expand All @@ -86,9 +86,9 @@
Path("README.md"),
Path("generate_clients.py"),
Path(".venv"),
Path("dist/"),
Path("templates/"),
Path("spec/"),
Path("dist"),
Path("templates"),
Path("spec"),
Path("PKG-INFO"),
]
EXCLUDE_EXTENSIONS = [
Expand Down Expand Up @@ -223,64 +223,56 @@ def _prepend_header_to_file(file_path: Path, header_file_path: Path) -> None:

def prepend_licenses() -> None:
logger.info("Re-applying license headers...")

# Combine all paths to exclude into one set.
all_excluded_paths = set(EXCLUDE_PATHS) | set(KEEP_TEST_FILES)

for file_path in CLIENT_DIR.rglob("*"):
if file_path.is_file():
relative_file_path = file_path.relative_to(CLIENT_DIR)
file_extension = ""
# If it's a "dotfile" like .keep
if (
relative_file_path.name.startswith(".")
and "." not in relative_file_path.name[1:]
):
# e.g., for '.keep', this is 'keep'
file_extension = relative_file_path.name.lstrip(".")
else:
# For standard files like generate_clients.py
file_extension = file_path.suffix.lstrip(".")

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

is_excluded = False
# Combine EXCLUDE_PATHS and KEEP_TEST_FILES for comprehensive exclusion check
# Convert Path objects in EXCLUDE_PATHS to strings for fnmatch compatibility
# Ensure patterns ending with '/' are handled for directory matching
all_exclude_patterns = [
str(p) + ("/" if p.is_dir() else "") for p in EXCLUDE_PATHS
] + [str(p) for p in KEEP_TEST_FILES]

for exclude_pattern_str in all_exclude_patterns:
# Handle direct file match or if the file is within an excluded directory
if fnmatch.fnmatch(str(relative_file_path), exclude_pattern_str) or (
exclude_pattern_str.endswith("/")
and str(relative_file_path).startswith(exclude_pattern_str)
):
is_excluded = True
break
if not file_path.is_file():
continue

relative_file_path = file_path.relative_to(CLIENT_DIR)

# Determine file extension, handling dotfiles.
file_extension = ""
if (
relative_file_path.name.startswith(".")
and "." not in relative_file_path.name[1:]
):
file_extension = relative_file_path.name.lstrip(".")
else:
file_extension = relative_file_path.suffix.lstrip(".")

if is_excluded:
logger.debug(f"{relative_file_path}: skipped (path excluded)")
continue
if file_extension in EXCLUDE_EXTENSIONS:
logger.debug(f"{relative_file_path}: skipped (extension excluded)")
continue

header_file_path = Path(
os.path.join(HEADER_DIR, f"header-{file_extension}.txt")
)
# Check if the path should be excluded.
is_excluded = False
for excluded_path in all_excluded_paths:
if relative_file_path == excluded_path or excluded_path in relative_file_path.parents:
is_excluded = True
break

if header_file_path.is_file():
_prepend_header_to_file(file_path, header_file_path)
logger.debug(f"{relative_file_path}: updated")
else:
logger.error(f"No header compatible with file {relative_file_path}")
sys.exit(2)
if is_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)
logger.debug(f"{relative_file_path}: updated")
else:
logger.error(f"No header compatible with file {relative_file_path}")
sys.exit(2)
logger.info("License fix complete.")


def prepare_spec_dir():
logger.info("Preparing spec directory...")
spec_dir = Path(SPEC_DIR)
spec_source_dir = Path(os.path.join(CLIENT_DIR.parent.parent, "spec"))
spec_source_dir = CLIENT_DIR.parent.parent / "spec"

if spec_source_dir.is_dir():
logger.info(f"Copying spec directory from {spec_source_dir} to {spec_dir}")
Expand Down