Post_Model.Py

None

!! class

Post class

"Post source"


        class Post(pydantic.BaseModel):
            markata: Any = None
            path: Path
            slug: Optional[str] = None
            href: Optional[str] = None
            published: bool = False
            description: Optional[str] = None
            content: str = None
            # date: Union[datetime.date, str]=None
            date: Optional[Union[datetime.date, str]] = None
            # pydantic.Field(
            # default_factory=lambda: datetime.date.min
            # )
            date_time: Optional[datetime.datetime] = None
            today: datetime.date = pydantic.Field(default_factory=datetime.date.today)
            now: datetime.datetime = pydantic.Field(default_factory=datetime.datetime.utcnow)
            load_time: float = 0
            profile: Optional[str] = None
            title: str = None
            model_config = ConfigDict(
                validate_assignment=True,
                arbitrary_types_allowed=True,
                extra="allow",
            )

            def __repr_args__(self: "Post") -> "ReprArgs":
                return [
                    (key, value)
                    for key, value in self.__dict__.items()
                    if key in self.markata.config.post_model.repr_include
                ]

            @property
            def metadata(self: "Post") -> Dict:
                "for backwards compatability"
                return self.__dict__

            def to_dict(self: "Post") -> Dict:
                "for backwards compatability"
                return self.__dict__

            def __getitem__(self: "Post", item: str) -> Any:
                "for backwards compatability"
                return getattr(self, item)

            def __setitem__(self: "Post", key: str, item: Any) -> None:
                "for backwards compatability"
                setattr(self, key, item)

            def get(self: "Post", item: str, default: Any) -> Any:
                "for backwards compatability"
                return getattr(self, item, default)

            def keys(self: "Post") -> List[str]:
                "for backwards compatability"
                return self.__dict__.keys()

            # def json(
            #     self: "Post",
            #     include: Iterable = None,
            #     all: bool = False,
            #     **kwargs,
            # ) -> str:
            #     """
            #     override function to give a default include value that will include
            #     user configured includes.
            #     """
            #     if all:
            #         return pydantic.create_model("Post", **self)(**self).json(
            #             **kwargs,
            #         )
            #     if include:
            #         return pydantic.create_model("Post", **self)(**self).json(
            #             include=include,
            #             **kwargs,
            #         )
            #     return pydantic.create_model("Post", **self)(**self).json(
            #         include={i: True for i in self.markata.config.post_model.include},
            #         **kwargs,
            #     )

            def yaml(self: "Post") -> str:
                """
                dump model to yaml
                """
                import yaml

                return yaml.dump(
                    self.dict(
                        include={i: True for i in self.markata.config.post_model.include}
                    ),
                    Dumper=yaml.CDumper,
                )

            def markdown(self: "Post") -> str:
                """
                dump model to markdown
                """

                import yaml

                frontmatter = yaml.dump(
                    self.dict(
                        include={
                            i: True
                            for i in [
                                _i
                                for _i in self.markata.config.post_model.include
                                if _i != "content"
                            ]
                        }
                    ),
                    Dumper=yaml.CDumper,
                )
                post = "---\n"
                post += frontmatter
                post += "---\n\n"

                if self.content:
                    post += self.content
                return post

            @classmethod
            def parse_file(cls, markata, path: Union[Path, str], **kwargs) -> "Post":
                if isinstance(path, Path):
                    if path.suffix in [".md", ".markdown"]:
                        return cls.parse_markdown(markata=markata, path=path, **kwargs)
                elif isinstance(path, str):
                    if path.endswith(".md") or path.endswith(".markdown"):
                        return cls.parse_markdown(markata=markata, path=path, **kwargs)
                return super(Post, cls).parse_file(path, **kwargs)

            @classmethod
            def parse_markdown(cls, markata, path: Union[Path, str], **kwargs) -> "Post":
                if isinstance(path, str):
                    path = Path(path)
                text = path.read_text()
                try:
                    _, fm, *content = text.split("---\n")
                    content = "---\n".join(content)
                    try:
                        fm = yaml.load(fm, Loader=yaml.CBaseLoader)
                    except yaml.YAMLError:
                        fm = {}
                except ValueError:
                    fm = {}
                    content = text
                if fm is None or isinstance(fm, str):
                    fm = {}

                post_args = {
                    "markata": markata,
                    "path": path,
                    "content": content,
                    **fm,
                }

                return markata.Post(**post_args)

            def dumps(self):
                """
                dumps raw article back out
                """
                return f"---\n{self.yaml()}\n\n---\n\n{self.content}"

            @pydantic.validator("slug", pre=True, always=True)
            def default_slug(cls, v, *, values):
                return v or slugify(str(values["path"].stem))

            @pydantic.validator("slug", pre=True, always=True)
            def index_slug_is_empty(cls, v, *, values):
                if v == "index":
                    return ""
                return v

            @pydantic.validator("href", pre=True, always=True)
            def default_href(cls, v, *, values):
                if v:
                    return v
                return f"/{values['slug'].strip('/')}/".replace("//", "/")

            @pydantic.validator("title", pre=True, always=True)
            def title_title(cls, v, *, values):
                title = v or Path(values["path"]).stem.replace("-", " ")
                return title.title()

            @pydantic.validator("date_time", pre=True, always=True)
            def dateparser_datetime(cls, v, *, values):
                if isinstance(v, str):
                    d = dateparser.parse(v)
                    if d is None:
                        raise ValueError(f'"{v}" is not a valid date')
                return v

            @pydantic.validator("date_time", pre=True, always=True)
            def date_is_datetime(cls, v, *, values):
                if v is None and "date" not in values:
                    values["markata"].console.log(f"{values['path']} has no date")
                    return datetime.datetime.now()
                if v is None and values["date"] is None:
                    values["markata"].console.log(f"{values['path']} has no date")
                    return datetime.datetime.now()
                if isinstance(v, datetime.datetime):
                    return v
                if isinstance(values["date"], datetime.datetime):
                    return values["date"]
                if isinstance(v, datetime.date):
                    return datetime.datetime.combine(v, datetime.time.min)
                if isinstance(values["date"], datetime.date):
                    return datetime.datetime.combine(values["date"], datetime.time.min)
                return v

            @pydantic.validator("date_time", pre=True, always=True)
            def mindate_time(cls, v, *, values):
                if v is None and "date" not in values:
                    values["markata"].console.log(f"{values['path']} has no date")
                    return datetime.datetime.min
                if values["date"] is None:
                    values["markata"].console.log(f"{values['path']} has no date")
                    return datetime.datetime.min
                if isinstance(v, datetime.datetime):
                    return v
                if isinstance(values["date"], datetime.datetime):
                    return values["date"]
                if isinstance(v, datetime.date):
                    return datetime.datetime.combine(v, datetime.time.min)
                if isinstance(values["date"], datetime.date):
                    return datetime.datetime.combine(values["date"], datetime.time.min)
                return v

            @pydantic.validator("date", pre=True, always=True)
            def dateparser_date(cls, v, *, values):
                if v is None:
                    return datetime.date.min
                if isinstance(v, str):
                    d = cls.markata.precache.get(v)
                    if d is not None:
                        return d
                    d = dateparser.parse(v)
                    if d is None:
                        raise ValueError(f'"{v}" is not a valid date')
                    d = d.date()
                    with cls.markata.cache as cache:
                        cache.add(v, d)
                    return d
                return v

!! class

PostModelConfig class

Configuration for the Post model

"PostModelConfig source"


        class PostModelConfig(pydantic.BaseModel):
            "Configuration for the Post model"

            def __init__(self, **data) -> None:
                """

                include: post attributes to include by default in Post
                model serialization.
                repr_include: post attributes to include by default in Post
                repr.  If `repr_include` is None, it will default to
                `include`, but it is likely that you want less in the repr
                than serialized output.

                example:

                ``` toml title='markata.toml'
                [markata.post_model]
                include = ['date', 'description', 'published',
                    'slug', 'title', 'content', 'html']
                repr_include = ['date', 'description', 'published', 'slug', 'title']
                ```
                """
                super().__init__(**data)

            include: List[str] = [
                "date",
                "description",
                "published",
                "slug",
                "title",
                "content",
                "html",
            ]
            repr_include: Optional[List[str]] = [
                "date",
                "description",
                "published",
                "slug",
                "title",
            ]

            @pydantic.validator("repr_include", pre=True, always=True)
            def repr_include_validator(cls, v, *, values):
                if v:
                    return v
                return values.get("include", None)

!! class

Config class

"Config source"


        class Config(pydantic.BaseModel):
            post_model: PostModelConfig = pydantic.Field(default_factory=PostModelConfig)

!! function

post_model function

"post_model source"


        def post_model(markata: "Markata") -> None:
            markata.post_models.append(Post)

!! function

config_model function

"config_model source"


        def config_model(markata: "Markata") -> None:
            markata.config_models.append(Config)

!! class

PostFactory class

"PostFactory source"


        class PostFactory(ModelFactory):
            __model__ = Post

!! method

repr_args method

"repr_args source"


        def __repr_args__(self: "Post") -> "ReprArgs":
                return [
                    (key, value)
                    for key, value in self.__dict__.items()
                    if key in self.markata.config.post_model.repr_include
                ]

!! method

metadata method

for backwards compatability

"metadata source"


        def metadata(self: "Post") -> Dict:
                "for backwards compatability"
                return self.__dict__

!! method

to_dict method

for backwards compatability

"to_dict source"


        def to_dict(self: "Post") -> Dict:
                "for backwards compatability"
                return self.__dict__

!! method

getitem method

for backwards compatability

"getitem source"


        def __getitem__(self: "Post", item: str) -> Any:
                "for backwards compatability"
                return getattr(self, item)

!! method

setitem method

for backwards compatability

"setitem source"


        def __setitem__(self: "Post", key: str, item: Any) -> None:
                "for backwards compatability"
                setattr(self, key, item)

!! method

get method

for backwards compatability

"get source"


        def get(self: "Post", item: str, default: Any) -> Any:
                "for backwards compatability"
                return getattr(self, item, default)

!! method

keys method

for backwards compatability

"keys source"


        def keys(self: "Post") -> List[str]:
                "for backwards compatability"
                return self.__dict__.keys()

!! method

yaml method

dump model to yaml

"yaml source"


        def yaml(self: "Post") -> str:
                """
                dump model to yaml
                """
                import yaml

                return yaml.dump(
                    self.dict(
                        include={i: True for i in self.markata.config.post_model.include}
                    ),
                    Dumper=yaml.CDumper,
                )

!! method

markdown method

dump model to markdown

"markdown source"


        def markdown(self: "Post") -> str:
                """
                dump model to markdown
                """

                import yaml

                frontmatter = yaml.dump(
                    self.dict(
                        include={
                            i: True
                            for i in [
                                _i
                                for _i in self.markata.config.post_model.include
                                if _i != "content"
                            ]
                        }
                    ),
                    Dumper=yaml.CDumper,
                )
                post = "---\n"
                post += frontmatter
                post += "---\n\n"

                if self.content:
                    post += self.content
                return post

!! method

parse_file method

"parse_file source"


        def parse_file(cls, markata, path: Union[Path, str], **kwargs) -> "Post":
                if isinstance(path, Path):
                    if path.suffix in [".md", ".markdown"]:
                        return cls.parse_markdown(markata=markata, path=path, **kwargs)
                elif isinstance(path, str):
                    if path.endswith(".md") or path.endswith(".markdown"):
                        return cls.parse_markdown(markata=markata, path=path, **kwargs)
                return super(Post, cls).parse_file(path, **kwargs)

!! method

parse_markdown method

"parse_markdown source"


        def parse_markdown(cls, markata, path: Union[Path, str], **kwargs) -> "Post":
                if isinstance(path, str):
                    path = Path(path)
                text = path.read_text()
                try:
                    _, fm, *content = text.split("---\n")
                    content = "---\n".join(content)
                    try:
                        fm = yaml.load(fm, Loader=yaml.CBaseLoader)
                    except yaml.YAMLError:
                        fm = {}
                except ValueError:
                    fm = {}
                    content = text
                if fm is None or isinstance(fm, str):
                    fm = {}

                post_args = {
                    "markata": markata,
                    "path": path,
                    "content": content,
                    **fm,
                }

                return markata.Post(**post_args)

!! method

dumps method

dumps raw article back out

"dumps source"


        def dumps(self):
                """
                dumps raw article back out
                """
                return f"---\n{self.yaml()}\n\n---\n\n{self.content}"

!! method

default_slug method

"default_slug source"


        def default_slug(cls, v, *, values):
                return v or slugify(str(values["path"].stem))

!! method

index_slug_is_empty method

"index_slug_is_empty source"


        def index_slug_is_empty(cls, v, *, values):
                if v == "index":
                    return ""
                return v

!! method

default_href method

"default_href source"


        def default_href(cls, v, *, values):
                if v:
                    return v
                return f"/{values['slug'].strip('/')}/".replace("//", "/")

!! method

title_title method

"title_title source"


        def title_title(cls, v, *, values):
                title = v or Path(values["path"]).stem.replace("-", " ")
                return title.title()

!! method

dateparser_datetime method

"dateparser_datetime source"


        def dateparser_datetime(cls, v, *, values):
                if isinstance(v, str):
                    d = dateparser.parse(v)
                    if d is None:
                        raise ValueError(f'"{v}" is not a valid date')
                return v

!! method

date_is_datetime method

"date_is_datetime source"


        def date_is_datetime(cls, v, *, values):
                if v is None and "date" not in values:
                    values["markata"].console.log(f"{values['path']} has no date")
                    return datetime.datetime.now()
                if v is None and values["date"] is None:
                    values["markata"].console.log(f"{values['path']} has no date")
                    return datetime.datetime.now()
                if isinstance(v, datetime.datetime):
                    return v
                if isinstance(values["date"], datetime.datetime):
                    return values["date"]
                if isinstance(v, datetime.date):
                    return datetime.datetime.combine(v, datetime.time.min)
                if isinstance(values["date"], datetime.date):
                    return datetime.datetime.combine(values["date"], datetime.time.min)
                return v

!! method

mindate_time method

"mindate_time source"


        def mindate_time(cls, v, *, values):
                if v is None and "date" not in values:
                    values["markata"].console.log(f"{values['path']} has no date")
                    return datetime.datetime.min
                if values["date"] is None:
                    values["markata"].console.log(f"{values['path']} has no date")
                    return datetime.datetime.min
                if isinstance(v, datetime.datetime):
                    return v
                if isinstance(values["date"], datetime.datetime):
                    return values["date"]
                if isinstance(v, datetime.date):
                    return datetime.datetime.combine(v, datetime.time.min)
                if isinstance(values["date"], datetime.date):
                    return datetime.datetime.combine(values["date"], datetime.time.min)
                return v

!! method

dateparser_date method

"dateparser_date source"


        def dateparser_date(cls, v, *, values):
                if v is None:
                    return datetime.date.min
                if isinstance(v, str):
                    d = cls.markata.precache.get(v)
                    if d is not None:
                        return d
                    d = dateparser.parse(v)
                    if d is None:
                        raise ValueError(f'"{v}" is not a valid date')
                    d = d.date()
                    with cls.markata.cache as cache:
                        cache.add(v, d)
                    return d
                return v

!! method

init method

include: post attributes to include by default in Post model serialization. repr_include: post attributes to include by default in Post repr. If repr_include is None, it will default to include, but it is likely that you want less in the repr than serialized output.
example:

``` toml title='markata.toml'
[markata.post_model]
include = ['date', 'description', 'published',
    'slug', 'title', 'content', 'html']
repr_include = ['date', 'description', 'published', 'slug', 'title']
```

"init source"


        def __init__(self, **data) -> None:
                """

                include: post attributes to include by default in Post
                model serialization.
                repr_include: post attributes to include by default in Post
                repr.  If `repr_include` is None, it will default to
                `include`, but it is likely that you want less in the repr
                than serialized output.

                example:

                ``` toml title='markata.toml'
                [markata.post_model]
                include = ['date', 'description', 'published',
                    'slug', 'title', 'content', 'html']
                repr_include = ['date', 'description', 'published', 'slug', 'title']
                ```
                """
                super().__init__(**data)

!! method

repr_include_validator method

"repr_include_validator source"


        def repr_include_validator(cls, v, *, values):
                if v:
                    return v
                return values.get("include", None)