# Path: psqlextra/types.py
# class PostgresPartitioningMethod(StrEnum):
#     """Methods of partitioning supported by PostgreSQL 11.x native support for
#     table partitioning."""
# 
#     RANGE = "range"
#     LIST = "list"
#     HASH = "hash"
# 
# Path: psqlextra/models/base.py
# class PostgresModel(models.Model):
#     """Base class for for taking advantage of PostgreSQL specific features."""
# 
#     class Meta:
#         abstract = True
#         base_manager_name = "objects"
# 
#     objects = PostgresManager()
# 
# Path: psqlextra/models/options.py
# class PostgresPartitionedModelOptions:
#     """Container for :see:PostgresPartitionedModel options.
# 
#     This is where attributes copied from the model's `PartitioningMeta`
#     are held.
#     """
# 
#     def __init__(self, method: PostgresPartitioningMethod, key: List[str]):
#         self.method = method
#         self.key = key
#         self.original_attrs: Dict[
#             str, Union[PostgresPartitioningMethod, List[str]]
#         ] = dict(method=method, key=key)


from django.db.models.base import ModelBase
from psqlextra.types import PostgresPartitioningMethod
from .base import PostgresModel
from .options import PostgresPartitionedModelOptions



class PostgresPartitionedModelMeta(ModelBase):
    """Custom meta class for :see:PostgresPartitionedModel.

    This meta class extracts attributes from the inner
    `PartitioningMeta` class and copies it onto a `_partitioning_meta`
    attribute. This is similar to how Django's `_meta` works.
    """

    default_method = PostgresPartitioningMethod.RANGE
    default_key = []

    def __new__(cls, name, bases, attrs, **kwargs):
        new_class = super().__new__(cls, name, bases, attrs, **kwargs)
        meta_class = attrs.pop("PartitioningMeta", None)

        method = getattr(meta_class, "method", None)
        key = getattr(meta_class, "key", None)

        patitioning_meta = PostgresPartitionedModelOptions(
            method=method or cls.default_method, key=key or cls.default_key
        )

        new_class.add_to_class("_partitioning_meta", patitioning_meta)
        return new_class


class PostgresPartitionedModel(

# Path: psqlextra/types.py
# class PostgresPartitioningMethod(StrEnum):
#     """Methods of partitioning supported by PostgreSQL 11.x native support for
#     table partitioning."""
# 
#     RANGE = "range"
#     LIST = "list"
#     HASH = "hash"
# 
# Path: psqlextra/models/base.py
# class PostgresModel(models.Model):
#     """Base class for for taking advantage of PostgreSQL specific features."""
# 
#     class Meta:
#         abstract = True
#         base_manager_name = "objects"
# 
#     objects = PostgresManager()
# 
# Path: psqlextra/models/options.py
# class PostgresPartitionedModelOptions:
#     """Container for :see:PostgresPartitionedModel options.
# 
#     This is where attributes copied from the model's `PartitioningMeta`
#     are held.
#     """
# 
#     def __init__(self, method: PostgresPartitioningMethod, key: List[str]):
#         self.method = method
#         self.key = key
#         self.original_attrs: Dict[
#             str, Union[PostgresPartitioningMethod, List[str]]
#         ] = dict(method=method, key=key)


# Path: psqlextra/models/partitioned.py
from django.db.models.base import ModelBase
from psqlextra.types import PostgresPartitioningMethod
from .base import PostgresModel
from .options import PostgresPartitionedModelOptions




class PostgresPartitionedModelMeta(ModelBase):
    """Custom meta class for :see:PostgresPartitionedModel.

    This meta class extracts attributes from the inner
    `PartitioningMeta` class and copies it onto a `_partitioning_meta`
    attribute. This is similar to how Django's `_meta` works.
    """

    default_method = PostgresPartitioningMethod.RANGE
    default_key = []

    def __new__(cls, name, bases, attrs, **kwargs):
        new_class = super().__new__(cls, name, bases, attrs, **kwargs)
        meta_class = attrs.pop("PartitioningMeta", None)

        method = getattr(meta_class, "method", None)
        key = getattr(meta_class, "key", None)

        patitioning_meta = PostgresPartitionedModelOptions(
            method=method or cls.default_method, key=key or cls.default_key
        )

        new_class.add_to_class("_partitioning_meta", patitioning_meta)
        return new_class


class PostgresPartitionedModel(

    PostgresModel, metaclass=PostgresPartitionedModelMeta