# Path: psqlextra/partitioning/error.py
# class PostgresPartitioningError(RuntimeError):
#     """Raised when the partitioning configuration is broken or automatically
#     creating/deleting partitions fails."""
# 
# Path: psqlextra/partitioning/range_partition.py
# class PostgresRangePartition(PostgresPartition):
#     """Base class for a PostgreSQL table partition in a range partitioned
#     table."""
# 
#     def __init__(self, from_values: Any, to_values: Any) -> None:
#         self.from_values = from_values
#         self.to_values = to_values
# 
#     def deconstruct(self) -> dict:
#         return {
#             **super().deconstruct(),
#             "from_values": self.from_values,
#             "to_values": self.to_values,
#         }
# 
#     def create(
#         self,
#         model: PostgresPartitionedModel,
#         schema_editor: PostgresSchemaEditor,
#         comment: Optional[str] = None,
#     ) -> None:
#         schema_editor.add_range_partition(
#             model=model,
#             name=self.name(),
#             from_values=self.from_values,
#             to_values=self.to_values,
#             comment=comment,
#         )
# 
#     def delete(
#         self,
#         model: PostgresPartitionedModel,
#         schema_editor: PostgresSchemaEditor,
#     ) -> None:
#         schema_editor.delete_partition(model, self.name())
# 
# Path: psqlextra/partitioning/time_partition_size.py
# class PostgresTimePartitionSize:
#     """Size of a time-based range partition table."""
# 
#     unit: PostgresTimePartitionUnit
#     value: int
# 
#     def __init__(
#         self,
#         years: Optional[int] = None,
#         months: Optional[int] = None,
#         weeks: Optional[int] = None,
#         days: Optional[int] = None,
#     ) -> None:
#         sizes = [years, months, weeks, days]
# 
#         if not any(sizes):
#             raise PostgresPartitioningError("Partition cannot be 0 in size.")
# 
#         if len([size for size in sizes if size and size > 0]) > 1:
#             raise PostgresPartitioningError(
#                 "Partition can only have on size unit."
#             )
# 
#         if years:
#             self.unit = PostgresTimePartitionUnit.YEARS
#             self.value = years
#         elif months:
#             self.unit = PostgresTimePartitionUnit.MONTHS
#             self.value = months
#         elif weeks:
#             self.unit = PostgresTimePartitionUnit.WEEKS
#             self.value = weeks
#         elif days:
#             self.unit = PostgresTimePartitionUnit.DAYS
#             self.value = days
#         else:
#             raise PostgresPartitioningError(
#                 "Unsupported time partitioning unit"
#             )
# 
#     def as_delta(self) -> relativedelta:
#         if self.unit == PostgresTimePartitionUnit.YEARS:
#             return relativedelta(years=self.value)
# 
#         if self.unit == PostgresTimePartitionUnit.MONTHS:
#             return relativedelta(months=self.value)
# 
#         if self.unit == PostgresTimePartitionUnit.WEEKS:
#             return relativedelta(weeks=self.value)
# 
#         if self.unit == PostgresTimePartitionUnit.DAYS:
#             return relativedelta(days=self.value)
# 
#         raise PostgresPartitioningError(
#             "Unsupported time partitioning unit: %s" % self.unit
#         )
# 
#     def start(self, dt: datetime) -> datetime:
#         if self.unit == PostgresTimePartitionUnit.YEARS:
#             return self._ensure_datetime(dt.replace(month=1, day=1))
# 
#         if self.unit == PostgresTimePartitionUnit.MONTHS:
#             return self._ensure_datetime(dt.replace(day=1))
# 
#         if self.unit == PostgresTimePartitionUnit.WEEKS:
#             return self._ensure_datetime(dt - relativedelta(days=dt.weekday()))
# 
#         return self._ensure_datetime(dt)
# 
#     @staticmethod
#     def _ensure_datetime(dt: Union[date, datetime]) -> datetime:
#         return datetime(year=dt.year, month=dt.month, day=dt.day)
# 
#     def __repr__(self) -> str:
#         return "PostgresTimePartitionSize<%s, %s>" % (self.unit, self.value)
# 
# class PostgresTimePartitionUnit(enum.Enum):
#     YEARS = "years"
#     MONTHS = "months"
#     WEEKS = "weeks"
#     DAYS = "days"


from datetime import datetime
from .error import PostgresPartitioningError
from .range_partition import PostgresRangePartition
from .time_partition_size import (
    PostgresTimePartitionSize,
    PostgresTimePartitionUnit,
)



class PostgresTimePartition(PostgresRangePartition):
    """Time-based range table partition.

    :see:PostgresTimePartitioningStrategy for more info.
    """

    _unit_name_format = {
        PostgresTimePartitionUnit.YEARS: "%Y",
        PostgresTimePartitionUnit.MONTHS: "%Y_%b",
        PostgresTimePartitionUnit.WEEKS: "%Y_week_%W",

# Path: psqlextra/partitioning/error.py
# class PostgresPartitioningError(RuntimeError):
#     """Raised when the partitioning configuration is broken or automatically
#     creating/deleting partitions fails."""
# 
# Path: psqlextra/partitioning/range_partition.py
# class PostgresRangePartition(PostgresPartition):
#     """Base class for a PostgreSQL table partition in a range partitioned
#     table."""
# 
#     def __init__(self, from_values: Any, to_values: Any) -> None:
#         self.from_values = from_values
#         self.to_values = to_values
# 
#     def deconstruct(self) -> dict:
#         return {
#             **super().deconstruct(),
#             "from_values": self.from_values,
#             "to_values": self.to_values,
#         }
# 
#     def create(
#         self,
#         model: PostgresPartitionedModel,
#         schema_editor: PostgresSchemaEditor,
#         comment: Optional[str] = None,
#     ) -> None:
#         schema_editor.add_range_partition(
#             model=model,
#             name=self.name(),
#             from_values=self.from_values,
#             to_values=self.to_values,
#             comment=comment,
#         )
# 
#     def delete(
#         self,
#         model: PostgresPartitionedModel,
#         schema_editor: PostgresSchemaEditor,
#     ) -> None:
#         schema_editor.delete_partition(model, self.name())
# 
# Path: psqlextra/partitioning/time_partition_size.py
# class PostgresTimePartitionSize:
#     """Size of a time-based range partition table."""
# 
#     unit: PostgresTimePartitionUnit
#     value: int
# 
#     def __init__(
#         self,
#         years: Optional[int] = None,
#         months: Optional[int] = None,
#         weeks: Optional[int] = None,
#         days: Optional[int] = None,
#     ) -> None:
#         sizes = [years, months, weeks, days]
# 
#         if not any(sizes):
#             raise PostgresPartitioningError("Partition cannot be 0 in size.")
# 
#         if len([size for size in sizes if size and size > 0]) > 1:
#             raise PostgresPartitioningError(
#                 "Partition can only have on size unit."
#             )
# 
#         if years:
#             self.unit = PostgresTimePartitionUnit.YEARS
#             self.value = years
#         elif months:
#             self.unit = PostgresTimePartitionUnit.MONTHS
#             self.value = months
#         elif weeks:
#             self.unit = PostgresTimePartitionUnit.WEEKS
#             self.value = weeks
#         elif days:
#             self.unit = PostgresTimePartitionUnit.DAYS
#             self.value = days
#         else:
#             raise PostgresPartitioningError(
#                 "Unsupported time partitioning unit"
#             )
# 
#     def as_delta(self) -> relativedelta:
#         if self.unit == PostgresTimePartitionUnit.YEARS:
#             return relativedelta(years=self.value)
# 
#         if self.unit == PostgresTimePartitionUnit.MONTHS:
#             return relativedelta(months=self.value)
# 
#         if self.unit == PostgresTimePartitionUnit.WEEKS:
#             return relativedelta(weeks=self.value)
# 
#         if self.unit == PostgresTimePartitionUnit.DAYS:
#             return relativedelta(days=self.value)
# 
#         raise PostgresPartitioningError(
#             "Unsupported time partitioning unit: %s" % self.unit
#         )
# 
#     def start(self, dt: datetime) -> datetime:
#         if self.unit == PostgresTimePartitionUnit.YEARS:
#             return self._ensure_datetime(dt.replace(month=1, day=1))
# 
#         if self.unit == PostgresTimePartitionUnit.MONTHS:
#             return self._ensure_datetime(dt.replace(day=1))
# 
#         if self.unit == PostgresTimePartitionUnit.WEEKS:
#             return self._ensure_datetime(dt - relativedelta(days=dt.weekday()))
# 
#         return self._ensure_datetime(dt)
# 
#     @staticmethod
#     def _ensure_datetime(dt: Union[date, datetime]) -> datetime:
#         return datetime(year=dt.year, month=dt.month, day=dt.day)
# 
#     def __repr__(self) -> str:
#         return "PostgresTimePartitionSize<%s, %s>" % (self.unit, self.value)
# 
# class PostgresTimePartitionUnit(enum.Enum):
#     YEARS = "years"
#     MONTHS = "months"
#     WEEKS = "weeks"
#     DAYS = "days"


# Path: psqlextra/partitioning/time_partition.py
from datetime import datetime
from .error import PostgresPartitioningError
from .range_partition import PostgresRangePartition
from .time_partition_size import (
    PostgresTimePartitionSize,
    PostgresTimePartitionUnit,
)




class PostgresTimePartition(PostgresRangePartition):
    """Time-based range table partition.

    :see:PostgresTimePartitioningStrategy for more info.
    """

    _unit_name_format = {
        PostgresTimePartitionUnit.YEARS: "%Y",
        PostgresTimePartitionUnit.MONTHS: "%Y_%b",
        PostgresTimePartitionUnit.WEEKS: "%Y_week_%W",

        PostgresTimePartitionUnit.DAYS: "%Y_%b_%d",