Module ezcv.content
This module is for handling all the functionality around content including:
- Getting the list of content directories
- Getting the metadata and contents of content files for sections
- Classes for parsing all extensions
Classes
Content
Base class for other Content types
Markdown
Used for parsing markdown content
Image
Used for parsing images
Functions
get_content_directories() -> List[str]: Gets a list of the existing content directories i.e. ["projects", "education"]
get_section_content() -> List[List[Union[defaultdict, str]]]: Takes in a section folder and gets all the content from the files using the Content subclass asigned to the file extension
Expand source code
"""This module is for handling all the functionality around content including:
- Getting the list of content directories
- Getting the metadata and contents of content files for sections
- Classes for parsing all extensions
Classes
-------
Content:
Base class for other Content types
Markdown:
Used for parsing markdown content
Image:
Used for parsing images
Functions
-------
get_content_directories() -> List[str]:
Gets a list of the existing content directories i.e. ["projects", "education"]
get_section_content() -> List[List[Union[defaultdict, str]]]:
Takes in a section folder and gets all the content from the files using the Content subclass asigned to the file extension
"""
# Standard Lib Dependencies
import os # Used primarily in path validation
from collections import defaultdict # Used to give dicts default args
from dataclasses import dataclass, field # Used to improve class performance
from typing import DefaultDict, List, Tuple, Type, Union # Used to provide accurate type hints
# Third Party Dependencies
import exifread # Used to get metadata of image files
import markdown # Used to render and read markdown files
from colored import fg # Used to highlight output with colors, especially errors/warnings
def get_content_directories() -> List[str]:
"""Gets a list of the existing content directories i.e. ["projects", "education"]
Returns
-------
List[str]:
The list of existing content directories i.e. ["projects", "education"]
"""
result:list[str] = []
for current_path in os.listdir("content"):
if os.path.isdir(os.path.join("content", current_path)):
result.append(os.path.join("content", current_path))
return result
def get_section_content(section_content_folder: str, examples: bool = False) -> List[List[Union[defaultdict, str]]]:
"""Takes in a section folder and gets all the content from the files using the Content subclass asigned to the file extension
Parameters
----------
section_content_folder : str
The string representation of the path to the section folder (i.e. 'content/education')
examples : bool, optional
Whether or not to render files with example in the name, by default False
Returns
-------
List[List[Union[defaultdict, str]]]
A list representing each file in the section of sublists where the metadata is the first element (as a defaultdict), and the HTML is the second (as a string)
Examples
--------
getting the section content of the education section
```
from ezcv.content import get_section_content
section_content_folder = 'content/education'
content = get_section_content(section_content_folder)
print(content[0]) # Prints [defaultdict(<function <lambda> at 0x000001F1B97CE040>, {'title': 'This is the title', 'company': 'This is the company'}), '<p>This is some content</p>']
```
"""
content:List[List[Union[defaultdict, str]]] = []
extension_handlers:DefaultDict[str, Type] = Content.get_available_extensions()
for file_name in os.listdir(section_content_folder): # Iterate through the section_content folder and get the content from each file
if not examples and file_name.startswith("example"):
continue
else:
extension = "." + file_name.lower().split(".")[-1] # Get the file extension
if extension_handlers[extension]: # Checking if there exists a Content subclass capable of handling the file
extension_handler = extension_handlers[extension]() # Instantiate the proper extension
# Get the content and add it to the list
metadata, html = extension_handler.get_content(os.path.join(section_content_folder, file_name))
content.append([metadata, html])
return content
@dataclass
class Content(dict):
"""Base class for other Content types
Notes
-----
- All subclasses are assumed to have implemented:
- __metadata__(); Returns a defaultdict of metadata
- __html__(); Returns the HTML to render
- A list attribute called extensions, for example in markdown it would be
extensions:List[str] = ['.md', '.markdown', '.mdown', '.mkdn', '.mkd', '.mdwn']
Methods
-------
get_available_extensions() -> DefaultDict[str, Type]:
Returns a defaultdict of available extensions and corresponding types to render them
Raises
------
NotImplementedError
If any of __metadata__(), or __html__() are not implemented in subclass
Examples
--------
### Get the list of extensions and their handlers
```
extension_handlers = Content.get_available_extensions()
print(extension_handlers) ''' defaultdict(
<function Content.get_available_extensions.<locals>.<lambda> at 0x00000240878690D0>,
{
'.md': <class '__main__.Markdown'>,
'.markdown': <class '__main__.Markdown'>,
'.jpg': <class '__main__.Image'>,
'.png': <class '__main__.Image'>
}
)'''
# Get an extension handler for a specific extension (in thise case .md files)
print(extension_handlers[".md"]) # <class '__main__.Markdown'>
```
### Get content of a list of files
```
content = [] # The list that
filenames = ['file.md', 'image.jpg'] # Gotten from somewhere else
extension_handlers = Content.get_available_extensions()
for current_file in filenames:
extension = '.' + current_file.split('.')[-1]
if extension_handlers[extension]:
extension_handler = extension_handlers[extension]()
metadata, html = extension_handler.get_content(current_file)
content.append([metadata, html])
```
"""
def get_available_extensions() -> DefaultDict[str, Type]:
"""Returns a defaultdict of extensions and corresponding child types to handle them
Returns
-------
DefaultDict[str, Type]:
A defaultdict with a str for the extension as a key, and the type as a value
"""
all_extensions:DefaultDict[str, Type] = defaultdict(lambda:False)
for current_class in Content.__subclasses__():
for extension in current_class.extensions:
all_extensions[extension] = current_class
return all_extensions
def __metadata__(self):
"""A function to be replaced with the specific implementation of generating metadata defauldict
Raises
------
NotImplementedError
If the function is not implemented in the subclass
"""
raise NotImplementedError
def get_content(self, file_path:str):
"""Generates the metadata and HTML from a peice of content
Parameters
----------
file_path : str
The path to the md file
Raises
------
NotImplementedError
If the function is not implemented in the subclass
"""
raise NotImplementedError
def __html__(self, file_path:str):
"""A function to be replaced with the specific implementation of generating HTML
Parameters
----------
file_path: (str)
The path for the file
Raises
------
NotImplementedError
If the function is not implemented in the subclass
"""
raise NotImplementedError
@dataclass
class Markdown(Content):
"""Used for parsing markdown content
Notes
-----
- Default extensions are
- [footnotes](https://python-markdown.github.io/extensions/footnotes/)
- [tables](https://python-markdown.github.io/extensions/tables/)
- [toc (Table of contents)](https://python-markdown.github.io/extensions/toc/)
- [abbr(abbreviations)](https://python-markdown.github.io/extensions/abbreviations/)
- [def_list(Definition lists)](https://python-markdown.github.io/extensions/definition_lists/)
- [sane_lists(Sane lists)](https://python-markdown.github.io/extensions/sane_lists/)
- [meta](https://python-markdown.github.io/extensions/meta)
- [mdx_math](https://github.com/mitya57/python-markdown-math)
Examples
--------
```
from ezcv.content import Markdown
html, metadata = Markdown().get_content('file_1.md')
```
"""
md:markdown.Markdown = markdown.Markdown(extensions=['meta', 'footnotes', 'tables', 'toc', 'abbr', 'def_list', 'sane_lists', "mdx_math"]) # Setup markdown parser with extensions
extensions:List[str] = (".md", ".markdown", ".mdown", ".mkdn", ".mkd", ".mdwn")
def __metadata__(self) -> defaultdict:
"""Gets the metadata from the YAML frontmatter of the markdown file
Notes
-----
- This class requires __html__ to be run first, or self.md to be set manually and run self.md.convert(text:str) over the text of the document
Returns
-------
defaultdict
Returns a defaultdict with the yaml metadata of a peice of content
"""
metadata:defaultdict = defaultdict(lambda:False)
for key in self.md.Meta: # Create defaultdict out of metadata
if type(self.md.Meta[key]) == list:
metadata[key] = self.md.Meta[key][0]
else:
metadata[key] = self.md.Meta[key]
return metadata
def __html__(self, file_path:str) -> str:
"""Parses the markdown file and returns a string with the resulting HTML
Parameters
----------
file_path : str
The path to the file to generate the HTML for
Returns
-------
str
The HTML rendered from the markdown file
"""
with open(f"{file_path}", "r") as mdfile: # Parse markdown file
text = mdfile.read()
html = self.md.convert(text) # Convert the markdown content text to hmtl
return html
def get_content(self, file_path: str) -> Tuple[defaultdict, str]:
"""Gets the html content of a file, and the metadata of the file
Parameters
----------
file_path : str
The path to the file to render
Returns
-------
str, defaultdict
Returns a defaultdict of the metadata first then the html content as a string
Raises
------
FileNotFoundError
If the provided file path does not exist
Examples
--------
Render a file called file_1.md
```
from ezcv.content import Markdown
metadata, html = Markdown().get_content('file_1.md')
```
"""
if not os.path.exists(file_path): # If file doesn't exist
raise FileNotFoundError(f"{fg(1)} Could not find file: {file_path}{fg(15)}\n")
html = self.__html__(file_path)
metadata = self.__metadata__()
return metadata, html
@dataclass
class Image(Content):
"""Used for parsing images
Notes
-----
- Exif data is NOT available on PNG images (it is only available of jpg and tiff)
- Since there are so many conditionals it is recommended to use the existing gallery stylesheet
Examples
--------
Render a file called 1.jpg
```
from ezcv.content import Image
metadata, html = Image().get_content('1.jpg')
```
"""
ignore_exif_data:bool = False
extensions:List[str] = (".jpg", ".png", ".jpeg", ".gif", ".svg", ".webp", ".apng", ".jfif", ".pjpeg", ".pjp")
image_paths:List[str] = field(default_factory=lambda: []) # TODO: find way to implement this properly
def __metadata__(self, filename:str) -> defaultdict:
"""Return the metadata of the file (and exif data if available)
Parameters
----------
filename : str
The path to the file to get the metadata from
Returns
-------
defaultdict
A defaultdict of the keys with the metadata in it
"""
if self.ignore_exif_data:
return defaultdict(lambda:False)
elif filename.lower().endswith("jpg"):
with open(filename ,"rb") as f:
tags = exifread.process_file(f)
tags = defaultdict(lambda:False, tags)
return tags
else:
return defaultdict(lambda:False)
def __html__(self, tags:defaultdict) -> str:
"""Parses the tags of the image and returns HTML for the EXIF data
Parameters
----------
file_path : str
The path to the file to generate the HTML for
Returns
-------
str
The HTML of the EXIF data from the file
"""
html = ""
# Lens detail
if tags['EXIF LensModel']:
html += f"<p class='lens'>{tags['EXIF LensModel']}</p>\n"
# Focal length
if tags['EXIF FocalLengthIn35mmFilm']:
if tags['EXIF FocalLengthIn35mmFilm'] != tags['EXIF FocalLength']:
html += f"<p class='focal-length'>{tags['EXIF FocalLengthIn35mmFilm']}mm (full frame equivalent)</p>\n"
else:
html += f"<p class='focal-length'>{tags['EXIF FocalLengthIn35mmFilm']}mm</p>\n"
else:
if tags['EXIF FocalLength']:
html += f"<p class='focal-length'>{tags['EXIF FocalLength']}mm</p>\n"
# ISO, Shutter speed, Apperture
if tags['EXIF ISOSpeedRatings']:
html += f"<p class='iso'>ISO {tags['EXIF ISOSpeedRatings']}</p>\n"
if tags['EXIF ExposureTime']:
html += f"<p class='shutter-speed'>{tags['EXIF ExposureTime']} Second(s)</p>\n"
if tags['EXIF FNumber']:
from fractions import Fraction
tags['EXIF FNumber'] = str(float(Fraction(str(tags['EXIF FNumber'])))) # Convert aperture to str i.e. 6.3
html += f"<p class='aperture'>f{tags['EXIF FNumber']}</p>\n"
# Camera body details
if tags['Image Make'] and tags['Image Model']:
html += f"<p class='camera-type'>{tags['Image Make']} {tags['Image Model']}</p>\n"
elif tags['Image Make']:
html += f"<p class='camera-type'>{tags['Image Make']}</p>\n"
elif tags["Image Model"]:
html += f"<p class='camera-type'>{tags['Image Model']}</p>\n"
else:
...
return html
def get_content(self, file_path: str) -> Tuple[defaultdict, str]:
"""Gets the html content of a file, and the metadata/exif of the file
Parameters
----------
file_path : str
The path to the file to render
Returns
-------
str, defaultdict
Returns the defaultdict of the metadata, and then the html of the exif data
Raises
------
FileNotFoundError
If the provided file path does not exist
Examples
--------
Render a file called 1.jpg
```
from ezcv.content import Image
metadata, html = Image().get_content('1.jpg')
```
"""
tags = self.__metadata__(file_path)
html = self.__html__(tags)
tags["file_path"] = f"images/gallery/{file_path.split(os.path.sep)[-1]}"
self.image_paths.append(file_path)
return tags, html
Functions
def get_content_directories() ‑> List[str]
-
Gets a list of the existing content directories i.e. ["projects", "education"]
Returns
List[str]:
- The list of existing content directories i.e. ["projects", "education"]
Expand source code
def get_content_directories() -> List[str]: """Gets a list of the existing content directories i.e. ["projects", "education"] Returns ------- List[str]: The list of existing content directories i.e. ["projects", "education"] """ result:list[str] = [] for current_path in os.listdir("content"): if os.path.isdir(os.path.join("content", current_path)): result.append(os.path.join("content", current_path)) return result
def get_section_content(section_content_folder: str, examples: bool = False) ‑> List[List[Union[collections.defaultdict, str]]]
-
Takes in a section folder and gets all the content from the files using the Content subclass asigned to the file extension
Parameters
section_content_folder
:str
- The string representation of the path to the section folder (i.e. 'content/education')
examples
:bool
, optional- Whether or not to render files with example in the name, by default False
Returns
List[List[Union[defaultdict, str]]]
- A list representing each file in the section of sublists where the metadata is the first element (as a defaultdict), and the HTML is the second (as a string)
Examples
getting the section content of the education section
from ezcv.content import get_section_content section_content_folder = 'content/education' content = get_section_content(section_content_folder) print(content[0]) # Prints [defaultdict(<function <lambda> at 0x000001F1B97CE040>, {'title': 'This is the title', 'company': 'This is the company'}), '<p>This is some content</p>']
Expand source code
def get_section_content(section_content_folder: str, examples: bool = False) -> List[List[Union[defaultdict, str]]]: """Takes in a section folder and gets all the content from the files using the Content subclass asigned to the file extension Parameters ---------- section_content_folder : str The string representation of the path to the section folder (i.e. 'content/education') examples : bool, optional Whether or not to render files with example in the name, by default False Returns ------- List[List[Union[defaultdict, str]]] A list representing each file in the section of sublists where the metadata is the first element (as a defaultdict), and the HTML is the second (as a string) Examples -------- getting the section content of the education section ``` from ezcv.content import get_section_content section_content_folder = 'content/education' content = get_section_content(section_content_folder) print(content[0]) # Prints [defaultdict(<function <lambda> at 0x000001F1B97CE040>, {'title': 'This is the title', 'company': 'This is the company'}), '<p>This is some content</p>'] ``` """ content:List[List[Union[defaultdict, str]]] = [] extension_handlers:DefaultDict[str, Type] = Content.get_available_extensions() for file_name in os.listdir(section_content_folder): # Iterate through the section_content folder and get the content from each file if not examples and file_name.startswith("example"): continue else: extension = "." + file_name.lower().split(".")[-1] # Get the file extension if extension_handlers[extension]: # Checking if there exists a Content subclass capable of handling the file extension_handler = extension_handlers[extension]() # Instantiate the proper extension # Get the content and add it to the list metadata, html = extension_handler.get_content(os.path.join(section_content_folder, file_name)) content.append([metadata, html]) return content
Classes
class Content
-
Base class for other Content types
Notes
- All subclasses are assumed to have implemented:
- metadata(); Returns a defaultdict of metadata
- html(); Returns the HTML to render
- A list attribute called extensions, for example in markdown it would be extensions:List[str] = ['.md', '.markdown', '.mdown', '.mkdn', '.mkd', '.mdwn']
Methods
get_available_extensions() -> DefaultDict[str, Type]: Returns a defaultdict of available extensions and corresponding types to render them
Raises
NotImplementedError
- If any of metadata(), or html() are not implemented in subclass
Examples
Get the list of extensions and their handlers
extension_handlers = Content.get_available_extensions() print(extension_handlers) ''' defaultdict( <function Content.get_available_extensions.<locals>.<lambda> at 0x00000240878690D0>, { '.md': <class '__main__.Markdown'>, '.markdown': <class '__main__.Markdown'>, '.jpg': <class '__main__.Image'>, '.png': <class '__main__.Image'> } )''' # Get an extension handler for a specific extension (in thise case .md files) print(extension_handlers[".md"]) # <class '__main__.Markdown'>
Get content of a list of files
content = [] # The list that filenames = ['file.md', 'image.jpg'] # Gotten from somewhere else extension_handlers = Content.get_available_extensions() for current_file in filenames: extension = '.' + current_file.split('.')[-1] if extension_handlers[extension]: extension_handler = extension_handlers[extension]() metadata, html = extension_handler.get_content(current_file) content.append([metadata, html])
Expand source code
@dataclass class Content(dict): """Base class for other Content types Notes ----- - All subclasses are assumed to have implemented: - __metadata__(); Returns a defaultdict of metadata - __html__(); Returns the HTML to render - A list attribute called extensions, for example in markdown it would be extensions:List[str] = ['.md', '.markdown', '.mdown', '.mkdn', '.mkd', '.mdwn'] Methods ------- get_available_extensions() -> DefaultDict[str, Type]: Returns a defaultdict of available extensions and corresponding types to render them Raises ------ NotImplementedError If any of __metadata__(), or __html__() are not implemented in subclass Examples -------- ### Get the list of extensions and their handlers ``` extension_handlers = Content.get_available_extensions() print(extension_handlers) ''' defaultdict( <function Content.get_available_extensions.<locals>.<lambda> at 0x00000240878690D0>, { '.md': <class '__main__.Markdown'>, '.markdown': <class '__main__.Markdown'>, '.jpg': <class '__main__.Image'>, '.png': <class '__main__.Image'> } )''' # Get an extension handler for a specific extension (in thise case .md files) print(extension_handlers[".md"]) # <class '__main__.Markdown'> ``` ### Get content of a list of files ``` content = [] # The list that filenames = ['file.md', 'image.jpg'] # Gotten from somewhere else extension_handlers = Content.get_available_extensions() for current_file in filenames: extension = '.' + current_file.split('.')[-1] if extension_handlers[extension]: extension_handler = extension_handlers[extension]() metadata, html = extension_handler.get_content(current_file) content.append([metadata, html]) ``` """ def get_available_extensions() -> DefaultDict[str, Type]: """Returns a defaultdict of extensions and corresponding child types to handle them Returns ------- DefaultDict[str, Type]: A defaultdict with a str for the extension as a key, and the type as a value """ all_extensions:DefaultDict[str, Type] = defaultdict(lambda:False) for current_class in Content.__subclasses__(): for extension in current_class.extensions: all_extensions[extension] = current_class return all_extensions def __metadata__(self): """A function to be replaced with the specific implementation of generating metadata defauldict Raises ------ NotImplementedError If the function is not implemented in the subclass """ raise NotImplementedError def get_content(self, file_path:str): """Generates the metadata and HTML from a peice of content Parameters ---------- file_path : str The path to the md file Raises ------ NotImplementedError If the function is not implemented in the subclass """ raise NotImplementedError def __html__(self, file_path:str): """A function to be replaced with the specific implementation of generating HTML Parameters ---------- file_path: (str) The path for the file Raises ------ NotImplementedError If the function is not implemented in the subclass """ raise NotImplementedError
Ancestors
- builtins.dict
Subclasses
Methods
def get_available_extensions() ‑> DefaultDict[str, Type]
-
Returns a defaultdict of extensions and corresponding child types to handle them
Returns
DefaultDict[str, Type]:
- A defaultdict with a str for the extension as a key, and the type as a value
Expand source code
def get_available_extensions() -> DefaultDict[str, Type]: """Returns a defaultdict of extensions and corresponding child types to handle them Returns ------- DefaultDict[str, Type]: A defaultdict with a str for the extension as a key, and the type as a value """ all_extensions:DefaultDict[str, Type] = defaultdict(lambda:False) for current_class in Content.__subclasses__(): for extension in current_class.extensions: all_extensions[extension] = current_class return all_extensions
def get_content(self, file_path: str)
-
Generates the metadata and HTML from a peice of content
Parameters
file_path
:str
- The path to the md file
Raises
NotImplementedError
- If the function is not implemented in the subclass
Expand source code
def get_content(self, file_path:str): """Generates the metadata and HTML from a peice of content Parameters ---------- file_path : str The path to the md file Raises ------ NotImplementedError If the function is not implemented in the subclass """ raise NotImplementedError
- All subclasses are assumed to have implemented:
class Image (ignore_exif_data: bool = False, extensions: List[str] = ('.jpg', '.png', '.jpeg', '.gif', '.svg', '.webp', '.apng', '.jfif', '.pjpeg', '.pjp'), image_paths: List[str] = <factory>)
-
Used for parsing images
Notes
- Exif data is NOT available on PNG images (it is only available of jpg and tiff)
- Since there are so many conditionals it is recommended to use the existing gallery stylesheet
Examples
Render a file called 1.jpg
from ezcv.content import Image metadata, html = Image().get_content('1.jpg')
Expand source code
@dataclass class Image(Content): """Used for parsing images Notes ----- - Exif data is NOT available on PNG images (it is only available of jpg and tiff) - Since there are so many conditionals it is recommended to use the existing gallery stylesheet Examples -------- Render a file called 1.jpg ``` from ezcv.content import Image metadata, html = Image().get_content('1.jpg') ``` """ ignore_exif_data:bool = False extensions:List[str] = (".jpg", ".png", ".jpeg", ".gif", ".svg", ".webp", ".apng", ".jfif", ".pjpeg", ".pjp") image_paths:List[str] = field(default_factory=lambda: []) # TODO: find way to implement this properly def __metadata__(self, filename:str) -> defaultdict: """Return the metadata of the file (and exif data if available) Parameters ---------- filename : str The path to the file to get the metadata from Returns ------- defaultdict A defaultdict of the keys with the metadata in it """ if self.ignore_exif_data: return defaultdict(lambda:False) elif filename.lower().endswith("jpg"): with open(filename ,"rb") as f: tags = exifread.process_file(f) tags = defaultdict(lambda:False, tags) return tags else: return defaultdict(lambda:False) def __html__(self, tags:defaultdict) -> str: """Parses the tags of the image and returns HTML for the EXIF data Parameters ---------- file_path : str The path to the file to generate the HTML for Returns ------- str The HTML of the EXIF data from the file """ html = "" # Lens detail if tags['EXIF LensModel']: html += f"<p class='lens'>{tags['EXIF LensModel']}</p>\n" # Focal length if tags['EXIF FocalLengthIn35mmFilm']: if tags['EXIF FocalLengthIn35mmFilm'] != tags['EXIF FocalLength']: html += f"<p class='focal-length'>{tags['EXIF FocalLengthIn35mmFilm']}mm (full frame equivalent)</p>\n" else: html += f"<p class='focal-length'>{tags['EXIF FocalLengthIn35mmFilm']}mm</p>\n" else: if tags['EXIF FocalLength']: html += f"<p class='focal-length'>{tags['EXIF FocalLength']}mm</p>\n" # ISO, Shutter speed, Apperture if tags['EXIF ISOSpeedRatings']: html += f"<p class='iso'>ISO {tags['EXIF ISOSpeedRatings']}</p>\n" if tags['EXIF ExposureTime']: html += f"<p class='shutter-speed'>{tags['EXIF ExposureTime']} Second(s)</p>\n" if tags['EXIF FNumber']: from fractions import Fraction tags['EXIF FNumber'] = str(float(Fraction(str(tags['EXIF FNumber'])))) # Convert aperture to str i.e. 6.3 html += f"<p class='aperture'>f{tags['EXIF FNumber']}</p>\n" # Camera body details if tags['Image Make'] and tags['Image Model']: html += f"<p class='camera-type'>{tags['Image Make']} {tags['Image Model']}</p>\n" elif tags['Image Make']: html += f"<p class='camera-type'>{tags['Image Make']}</p>\n" elif tags["Image Model"]: html += f"<p class='camera-type'>{tags['Image Model']}</p>\n" else: ... return html def get_content(self, file_path: str) -> Tuple[defaultdict, str]: """Gets the html content of a file, and the metadata/exif of the file Parameters ---------- file_path : str The path to the file to render Returns ------- str, defaultdict Returns the defaultdict of the metadata, and then the html of the exif data Raises ------ FileNotFoundError If the provided file path does not exist Examples -------- Render a file called 1.jpg ``` from ezcv.content import Image metadata, html = Image().get_content('1.jpg') ``` """ tags = self.__metadata__(file_path) html = self.__html__(tags) tags["file_path"] = f"images/gallery/{file_path.split(os.path.sep)[-1]}" self.image_paths.append(file_path) return tags, html
Ancestors
- Content
- builtins.dict
Class variables
var extensions : List[str]
var ignore_exif_data : bool
var image_paths : List[str]
Methods
def get_content(self, file_path: str) ‑> Tuple[collections.defaultdict, str]
-
Gets the html content of a file, and the metadata/exif of the file
Parameters
file_path
:str
- The path to the file to render
Returns
str, defaultdict
- Returns the defaultdict of the metadata, and then the html of the exif data
Raises
FileNotFoundError
- If the provided file path does not exist
Examples
Render a file called 1.jpg
from ezcv.content import Image metadata, html = Image().get_content('1.jpg')
Expand source code
def get_content(self, file_path: str) -> Tuple[defaultdict, str]: """Gets the html content of a file, and the metadata/exif of the file Parameters ---------- file_path : str The path to the file to render Returns ------- str, defaultdict Returns the defaultdict of the metadata, and then the html of the exif data Raises ------ FileNotFoundError If the provided file path does not exist Examples -------- Render a file called 1.jpg ``` from ezcv.content import Image metadata, html = Image().get_content('1.jpg') ``` """ tags = self.__metadata__(file_path) html = self.__html__(tags) tags["file_path"] = f"images/gallery/{file_path.split(os.path.sep)[-1]}" self.image_paths.append(file_path) return tags, html
Inherited members
class Markdown (md: markdown.core.Markdown = <markdown.core.Markdown object>, extensions: List[str] = ('.md', '.markdown', '.mdown', '.mkdn', '.mkd', '.mdwn'))
-
Used for parsing markdown content
Notes
- Default extensions are
Examples
from ezcv.content import Markdown html, metadata = Markdown().get_content('file_1.md')
Expand source code
@dataclass class Markdown(Content): """Used for parsing markdown content Notes ----- - Default extensions are - [footnotes](https://python-markdown.github.io/extensions/footnotes/) - [tables](https://python-markdown.github.io/extensions/tables/) - [toc (Table of contents)](https://python-markdown.github.io/extensions/toc/) - [abbr(abbreviations)](https://python-markdown.github.io/extensions/abbreviations/) - [def_list(Definition lists)](https://python-markdown.github.io/extensions/definition_lists/) - [sane_lists(Sane lists)](https://python-markdown.github.io/extensions/sane_lists/) - [meta](https://python-markdown.github.io/extensions/meta) - [mdx_math](https://github.com/mitya57/python-markdown-math) Examples -------- ``` from ezcv.content import Markdown html, metadata = Markdown().get_content('file_1.md') ``` """ md:markdown.Markdown = markdown.Markdown(extensions=['meta', 'footnotes', 'tables', 'toc', 'abbr', 'def_list', 'sane_lists', "mdx_math"]) # Setup markdown parser with extensions extensions:List[str] = (".md", ".markdown", ".mdown", ".mkdn", ".mkd", ".mdwn") def __metadata__(self) -> defaultdict: """Gets the metadata from the YAML frontmatter of the markdown file Notes ----- - This class requires __html__ to be run first, or self.md to be set manually and run self.md.convert(text:str) over the text of the document Returns ------- defaultdict Returns a defaultdict with the yaml metadata of a peice of content """ metadata:defaultdict = defaultdict(lambda:False) for key in self.md.Meta: # Create defaultdict out of metadata if type(self.md.Meta[key]) == list: metadata[key] = self.md.Meta[key][0] else: metadata[key] = self.md.Meta[key] return metadata def __html__(self, file_path:str) -> str: """Parses the markdown file and returns a string with the resulting HTML Parameters ---------- file_path : str The path to the file to generate the HTML for Returns ------- str The HTML rendered from the markdown file """ with open(f"{file_path}", "r") as mdfile: # Parse markdown file text = mdfile.read() html = self.md.convert(text) # Convert the markdown content text to hmtl return html def get_content(self, file_path: str) -> Tuple[defaultdict, str]: """Gets the html content of a file, and the metadata of the file Parameters ---------- file_path : str The path to the file to render Returns ------- str, defaultdict Returns a defaultdict of the metadata first then the html content as a string Raises ------ FileNotFoundError If the provided file path does not exist Examples -------- Render a file called file_1.md ``` from ezcv.content import Markdown metadata, html = Markdown().get_content('file_1.md') ``` """ if not os.path.exists(file_path): # If file doesn't exist raise FileNotFoundError(f"{fg(1)} Could not find file: {file_path}{fg(15)}\n") html = self.__html__(file_path) metadata = self.__metadata__() return metadata, html
Ancestors
- Content
- builtins.dict
Class variables
var extensions : List[str]
var md : markdown.core.Markdown
Methods
def get_content(self, file_path: str) ‑> Tuple[collections.defaultdict, str]
-
Gets the html content of a file, and the metadata of the file
Parameters
file_path
:str
- The path to the file to render
Returns
str, defaultdict
- Returns a defaultdict of the metadata first then the html content as a string
Raises
FileNotFoundError
- If the provided file path does not exist
Examples
Render a file called file_1.md
from ezcv.content import Markdown metadata, html = Markdown().get_content('file_1.md')
Expand source code
def get_content(self, file_path: str) -> Tuple[defaultdict, str]: """Gets the html content of a file, and the metadata of the file Parameters ---------- file_path : str The path to the file to render Returns ------- str, defaultdict Returns a defaultdict of the metadata first then the html content as a string Raises ------ FileNotFoundError If the provided file path does not exist Examples -------- Render a file called file_1.md ``` from ezcv.content import Markdown metadata, html = Markdown().get_content('file_1.md') ``` """ if not os.path.exists(file_path): # If file doesn't exist raise FileNotFoundError(f"{fg(1)} Could not find file: {file_path}{fg(15)}\n") html = self.__html__(file_path) metadata = self.__metadata__() return metadata, html
Inherited members