first commit
commit
ffb97bcf81
@ -0,0 +1,2 @@
|
|||||||
|
.DS_Store
|
||||||
|
venv/
|
@ -0,0 +1,389 @@
|
|||||||
|
import os
|
||||||
|
import shutil
|
||||||
|
import json
|
||||||
|
import subprocess
|
||||||
|
import markdown
|
||||||
|
from jinja2 import Environment, FileSystemLoader
|
||||||
|
|
||||||
|
|
||||||
|
def delete_project():
|
||||||
|
|
||||||
|
cms_file = "cms.json"
|
||||||
|
|
||||||
|
if not os.path.exists(cms_file):
|
||||||
|
print("No projects found. Please generate a template directory first.")
|
||||||
|
return
|
||||||
|
|
||||||
|
with open(cms_file, 'r') as f:
|
||||||
|
cms_data = json.load(f)
|
||||||
|
|
||||||
|
# Check if categories exist
|
||||||
|
if not cms_data.get("categories"):
|
||||||
|
print("Error: No categories found in the CMS.")
|
||||||
|
return
|
||||||
|
|
||||||
|
# List available projects
|
||||||
|
print("Available projects:")
|
||||||
|
for i, (project_slug, project_data) in enumerate(cms_data["projects"].items(), start=1):
|
||||||
|
project_name = project_data.get("name", "")
|
||||||
|
print("{}. {}".format(i, project_name))
|
||||||
|
|
||||||
|
# Ask user to choose a project to edit
|
||||||
|
project_index = int(input("Enter the number of the project to edit: ")) - 1
|
||||||
|
project_slug = list(cms_data["projects"].keys())[project_index]
|
||||||
|
|
||||||
|
cms_data['projects'].pop(project_slug)
|
||||||
|
|
||||||
|
|
||||||
|
with open(cms_file, 'w') as file:
|
||||||
|
json.dump(cms_data, file, indent=2)
|
||||||
|
|
||||||
|
shutil.rmtree(f'website/projects/{project_slug}')
|
||||||
|
|
||||||
|
print(f"Removed '{project_index}' from the projects.")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def generate_template():
|
||||||
|
project_name_it = input("Enter the name of the project in italian: ")
|
||||||
|
project_name_en = input("Enter the name of the project in english: ")
|
||||||
|
project_slug = project_name_it.lower().replace(" ", "_")
|
||||||
|
|
||||||
|
project_dir = os.path.join("website/projects", project_slug)
|
||||||
|
en_dir = os.path.join(project_dir, "en")
|
||||||
|
assets_dir = os.path.join(project_dir, "assets")
|
||||||
|
markdown_file = os.path.join(project_dir, "content.md")
|
||||||
|
markdown_en_file = os.path.join(en_dir, "content.md")
|
||||||
|
cms_file = "cms.json"
|
||||||
|
|
||||||
|
os.makedirs(en_dir, exist_ok=True)
|
||||||
|
os.makedirs(assets_dir, exist_ok=True)
|
||||||
|
open(markdown_file, 'a').close() # Create empty markdown files
|
||||||
|
open(markdown_en_file, 'a').close()
|
||||||
|
|
||||||
|
# Update or create a key in the JSON file
|
||||||
|
if os.path.exists(cms_file):
|
||||||
|
with open(cms_file, 'r') as f:
|
||||||
|
cms_data = json.load(f)
|
||||||
|
else:
|
||||||
|
os.makedirs("website/en", exist_ok=True)
|
||||||
|
cms_data = {"projects":{}, "categories":[]} # Initialize categories list
|
||||||
|
|
||||||
|
cms_data["projects"][project_slug] = {"name": [project_name_it, project_name_en]}
|
||||||
|
|
||||||
|
with open(cms_file, 'w') as f:
|
||||||
|
json.dump(cms_data, f, indent=4)
|
||||||
|
|
||||||
|
print("Template directory created for project '{}'.\n"
|
||||||
|
"Add images to '{}' and write content in '{}'.".format(project_name_it, assets_dir, markdown_file))
|
||||||
|
|
||||||
|
|
||||||
|
def add_categories_to_cms():
|
||||||
|
cms_file = "cms.json"
|
||||||
|
|
||||||
|
if not os.path.exists(cms_file):
|
||||||
|
print("No projects found. Please generate a template directory first.")
|
||||||
|
return
|
||||||
|
|
||||||
|
with open(cms_file, 'r') as f:
|
||||||
|
cms_data = json.load(f)
|
||||||
|
|
||||||
|
category = []
|
||||||
|
categories = cms_data.get("categories", [])
|
||||||
|
categoryIt = input("Enter the name of the category to add in italian: ")
|
||||||
|
categoryEn = input("Enter the name of the category to add in english: ")
|
||||||
|
|
||||||
|
category = [categoryIt, categoryEn]
|
||||||
|
|
||||||
|
|
||||||
|
categories.append(category)
|
||||||
|
|
||||||
|
cms_data["categories"] = categories
|
||||||
|
|
||||||
|
with open(cms_file, 'w') as f:
|
||||||
|
json.dump(cms_data, f, indent=4)
|
||||||
|
|
||||||
|
print("Category '{}' added to CMS.".format(category))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def prepare_project():
|
||||||
|
cms_file = "cms.json"
|
||||||
|
|
||||||
|
if not os.path.exists(cms_file):
|
||||||
|
print("No projects found. Please generate a template directory first.")
|
||||||
|
return
|
||||||
|
|
||||||
|
with open(cms_file, 'r') as f:
|
||||||
|
cms_data = json.load(f)
|
||||||
|
|
||||||
|
# Check if categories exist
|
||||||
|
if not cms_data.get("categories"):
|
||||||
|
print("Error: No categories found in the CMS.")
|
||||||
|
return
|
||||||
|
|
||||||
|
# List available projects
|
||||||
|
print("Available projects:")
|
||||||
|
for i, (project_slug, project_data) in enumerate(cms_data["projects"].items(), start=1):
|
||||||
|
project_name = project_data.get("name", "")
|
||||||
|
print("{}. {}".format(i, project_name))
|
||||||
|
|
||||||
|
# Ask user to choose a project to edit
|
||||||
|
project_index = int(input("Enter the number of the project to edit: ")) - 1
|
||||||
|
project_slug = list(cms_data["projects"].keys())[project_index]
|
||||||
|
project_data = cms_data["projects"][project_slug]
|
||||||
|
project_name = project_data.get("name", "")
|
||||||
|
|
||||||
|
# List available categories
|
||||||
|
print("Available categories:")
|
||||||
|
for i, category in enumerate(cms_data["categories"], start=1):
|
||||||
|
print("{}. {}".format(i, category))
|
||||||
|
|
||||||
|
# Check if there are no categories
|
||||||
|
if not cms_data["categories"]:
|
||||||
|
print("Error: No categories found in the CMS.")
|
||||||
|
return
|
||||||
|
|
||||||
|
# Ask user to choose a category
|
||||||
|
category_index = int(input("Enter the number of the category to assign to the project: ")) - 1
|
||||||
|
selected_category = cms_data["categories"][category_index]
|
||||||
|
|
||||||
|
# Update project data with the selected category
|
||||||
|
project_data["category"] = selected_category
|
||||||
|
|
||||||
|
# Proceed with editing the selected project
|
||||||
|
project_dir = os.path.join("website/projects", project_slug)
|
||||||
|
en_dir = os.path.join(project_dir, "en")
|
||||||
|
assets_dir = os.path.join(project_dir, "assets")
|
||||||
|
# compressed_dir = os.path.join(assets_dir, "compressed")
|
||||||
|
markdown_file = os.path.join(project_dir, "content.md")
|
||||||
|
markdown_en_file = os.path.join(en_dir, "content.md")
|
||||||
|
|
||||||
|
# Check if assets folder exists
|
||||||
|
if not os.path.exists(assets_dir):
|
||||||
|
print("Error: Assets folder not found for project '{}'. "
|
||||||
|
"Please make sure the 'assets' folder exists.".format(project_name))
|
||||||
|
return
|
||||||
|
|
||||||
|
# Check if there are no pictures in the assets folder
|
||||||
|
if not os.listdir(assets_dir):
|
||||||
|
print("Error: No pictures found in the 'assets' folder for project '{}'."
|
||||||
|
" Please add pictures before proceeding.".format(project_name))
|
||||||
|
return
|
||||||
|
|
||||||
|
# Compress/resize images
|
||||||
|
# os.makedirs(compressed_dir, exist_ok=True)
|
||||||
|
image_files = [f for f in os.listdir(assets_dir) if os.path.isfile(os.path.join(assets_dir, f))]
|
||||||
|
for image_file in image_files:
|
||||||
|
subprocess.run(["convert", os.path.join(assets_dir, image_file), "-resize", "50%", "-define", "jpeg:extent=512kb", os.path.join(assets_dir, image_file)])
|
||||||
|
|
||||||
|
# Prompt user to select main picture
|
||||||
|
print("Available pictures:")
|
||||||
|
for i, image_file in enumerate(image_files, start=1):
|
||||||
|
print("{}. {}".format(i, image_file))
|
||||||
|
print("Enter the number of the main picture (or press Enter to keep current): ")
|
||||||
|
main_picture_index = input()
|
||||||
|
if main_picture_index:
|
||||||
|
main_picture_index = int(main_picture_index) - 1
|
||||||
|
if 0 <= main_picture_index < len(image_files):
|
||||||
|
main_picture = image_files[main_picture_index]
|
||||||
|
else:
|
||||||
|
print("Invalid picture number. Keeping current main picture.")
|
||||||
|
main_picture = project_data.get("main_picture", "")
|
||||||
|
else:
|
||||||
|
main_picture = project_data.get("main_picture", "")
|
||||||
|
|
||||||
|
# Prompt user to choose if main picture appears in the gallery
|
||||||
|
main_in_gallery = True
|
||||||
|
main_in_gallery_boolean = input("Do you want the main picture be in the gallery? Yes / No :")
|
||||||
|
if main_in_gallery_boolean == "yes" or main_in_gallery_boolean == "Yes":
|
||||||
|
main_in_gallery = True
|
||||||
|
else:
|
||||||
|
main_in_gallery = False
|
||||||
|
|
||||||
|
# Prompt user to update captions for images
|
||||||
|
captions_it = project_data.get("captions_it", {})
|
||||||
|
captions_en = project_data.get("captions_en", {})
|
||||||
|
for image_file in image_files:
|
||||||
|
if not main_in_gallery:
|
||||||
|
if image_file == main_picture:
|
||||||
|
continue
|
||||||
|
|
||||||
|
print("Current caption for '{}' (Italian): {}".format(image_file, captions_it.get(image_file, "No caption")))
|
||||||
|
new_caption_it = input("Enter new caption for '{}' (Italian) (press Enter to keep current): ".format(image_file)).strip()
|
||||||
|
if new_caption_it:
|
||||||
|
captions_it[image_file] = new_caption_it
|
||||||
|
elif image_file not in captions_it:
|
||||||
|
captions_it[image_file] = ""
|
||||||
|
|
||||||
|
print("Current caption for '{}' (English): {}".format(image_file, captions_en.get(image_file, "No caption")))
|
||||||
|
new_caption_en = input("Enter new caption for '{}' (English) (press Enter to keep current): ".format(image_file)).strip()
|
||||||
|
if new_caption_en:
|
||||||
|
captions_en[image_file] = new_caption_en
|
||||||
|
elif image_file not in captions_en:
|
||||||
|
captions_en[image_file] = ""
|
||||||
|
|
||||||
|
# Prompt user to update video URL
|
||||||
|
print("Current video URL: {}".format(project_data.get("video_url", "None")))
|
||||||
|
video_url = input("Enter new video URL (press Enter to keep current): ").strip()
|
||||||
|
if not video_url:
|
||||||
|
video_url = project_data.get("video_url", "")
|
||||||
|
|
||||||
|
# Convert markdown file to HTML for Italian
|
||||||
|
with open(markdown_file, 'r') as f:
|
||||||
|
markdown_content_it = f.read()
|
||||||
|
markdown_content_it = markdown.markdown(markdown_content_it)
|
||||||
|
html_content_it = markdown_content_it
|
||||||
|
|
||||||
|
# Convert markdown file to HTML for English
|
||||||
|
with open(markdown_en_file, 'r') as f:
|
||||||
|
markdown_content_en = f.read()
|
||||||
|
markdown_content_en = markdown.markdown(markdown_content_en)
|
||||||
|
html_content_en = markdown_content_en
|
||||||
|
|
||||||
|
# Update project data in JSON file
|
||||||
|
project_data["main_picture"] = main_picture
|
||||||
|
project_data["captions_it"] = captions_it
|
||||||
|
project_data["captions_en"] = captions_en
|
||||||
|
project_data["video_url"] = video_url
|
||||||
|
project_data["html_content_it"] = html_content_it
|
||||||
|
project_data["html_content_en"] = html_content_en
|
||||||
|
|
||||||
|
|
||||||
|
# Save updated JSON file
|
||||||
|
with open(cms_file, 'w') as f:
|
||||||
|
json.dump(cms_data, f, indent=4)
|
||||||
|
|
||||||
|
print("Project preparation complete.")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def generate_website():
|
||||||
|
cms_file = "cms.json"
|
||||||
|
|
||||||
|
if not os.path.exists(cms_file):
|
||||||
|
print("No projects found. Please generate a template directory first.")
|
||||||
|
return
|
||||||
|
|
||||||
|
with open(cms_file, 'r') as f:
|
||||||
|
cms_data = json.load(f)
|
||||||
|
|
||||||
|
# markdown misc content
|
||||||
|
misc_content_en = {}
|
||||||
|
misc_content_it = {}
|
||||||
|
|
||||||
|
# Get a list of Markdown files in the 'en' folder
|
||||||
|
markdown_files_en = [f for f in os.listdir('misc/en') if f.endswith('.md')]
|
||||||
|
|
||||||
|
# Iterate through each Markdown file in the 'en' folder
|
||||||
|
for file_name in markdown_files_en:
|
||||||
|
file_path = os.path.join('misc/en', file_name)
|
||||||
|
|
||||||
|
# Read the content of the Markdown file
|
||||||
|
with open(file_path, 'r', encoding='utf-8') as file:
|
||||||
|
content = file.read()
|
||||||
|
|
||||||
|
# Convert Markdown content to HTML
|
||||||
|
html_content = markdown.markdown(content)
|
||||||
|
|
||||||
|
# Store the HTML content in the dictionary with the file name as the key
|
||||||
|
misc_content_en[file_name.replace('.md','')] = html_content
|
||||||
|
|
||||||
|
# Get a list of Markdown files in the 'it' folder
|
||||||
|
markdown_files_it = [f for f in os.listdir('misc/it') if f.endswith('.md')]
|
||||||
|
|
||||||
|
# Iterate through each Markdown file in the 'it' folder
|
||||||
|
for file_name in markdown_files_it:
|
||||||
|
file_path = os.path.join('misc/it', file_name)
|
||||||
|
|
||||||
|
# Read the content of the Markdown file
|
||||||
|
with open(file_path, 'r', encoding='utf-8') as file:
|
||||||
|
content = file.read()
|
||||||
|
|
||||||
|
# Convert Markdown content to HTML
|
||||||
|
html_content = markdown.markdown(content)
|
||||||
|
|
||||||
|
# Store the HTML content in the dictionary with the file name as the key
|
||||||
|
misc_content_it[file_name.replace('.md','')] = html_content
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
gallery_pics = [f for f in os.listdir('website/galleria') if not f.startswith('.')]
|
||||||
|
|
||||||
|
# Get gallery images
|
||||||
|
# os.makedirs('website/galleria/compressed', exist_ok=True)
|
||||||
|
|
||||||
|
# Compress/resize images
|
||||||
|
for gallery_pic in gallery_pics:
|
||||||
|
if not gallery_pic.endswith('compressed'):
|
||||||
|
subprocess.run(["convert", os.path.join('website/galleria', gallery_pic), "-resize", "50%", "-define", "jpeg:extent=512kb", os.path.join('website/galleria/', gallery_pic)])
|
||||||
|
|
||||||
|
# Initialize Jinja environment
|
||||||
|
env = Environment(loader=FileSystemLoader('.'))
|
||||||
|
|
||||||
|
# Render index page
|
||||||
|
# In italian
|
||||||
|
index_template_it = env.get_template('template/index_template.html')
|
||||||
|
index_html_it = index_template_it.render(cms_data=cms_data, gallery_pics=gallery_pics, misc_content=misc_content_it)
|
||||||
|
|
||||||
|
with open('website/index.html', 'w') as index_file:
|
||||||
|
index_file.write(index_html_it)
|
||||||
|
|
||||||
|
# In english
|
||||||
|
index_template_en = env.get_template('template/index_template_en.html')
|
||||||
|
index_html_en = index_template_en.render(cms_data=cms_data, gallery_pics=gallery_pics, misc_content=misc_content_en)
|
||||||
|
|
||||||
|
with open('website/en/index.html', 'w') as index_file:
|
||||||
|
index_file.write(index_html_en)
|
||||||
|
|
||||||
|
|
||||||
|
# Render project pages
|
||||||
|
|
||||||
|
# In Italian
|
||||||
|
project_template = env.get_template('template/project_template.html')
|
||||||
|
|
||||||
|
for project, values in cms_data["projects"].items():
|
||||||
|
project_html = project_template.render(values=values, cms_data=cms_data, misc_content=misc_content_it)
|
||||||
|
project_dir = os.path.join("website/projects", project)
|
||||||
|
with open(os.path.join(project_dir, "index.html"), 'w') as project_file:
|
||||||
|
project_file.write(project_html)
|
||||||
|
|
||||||
|
# In english
|
||||||
|
project_template_en = env.get_template('template/project_template_en.html')
|
||||||
|
|
||||||
|
for project, values in cms_data["projects"].items():
|
||||||
|
project_html = project_template_en.render(values=values, cms_data=cms_data, misc_content=misc_content_en)
|
||||||
|
project_dir = os.path.join("website/projects/", project,'en/')
|
||||||
|
with open(os.path.join(project_dir, "index.html"), 'w') as project_file:
|
||||||
|
project_file.write(project_html)
|
||||||
|
|
||||||
|
print("Website generation complete.")
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
print("Select an option:")
|
||||||
|
print("1. Generate a template directory")
|
||||||
|
print("2. Prepare a project by scanning the directory")
|
||||||
|
print("3. Add categories")
|
||||||
|
print("4. Generate the website")
|
||||||
|
print("5. Delete a project")
|
||||||
|
print("6. Exit")
|
||||||
|
choice = input("Enter your choice (1, 2, 3, 4, or 5): ")
|
||||||
|
|
||||||
|
if choice == '1':
|
||||||
|
generate_template()
|
||||||
|
elif choice == '2':
|
||||||
|
prepare_project()
|
||||||
|
elif choice == '3':
|
||||||
|
add_categories_to_cms()
|
||||||
|
elif choice == '4':
|
||||||
|
generate_website()
|
||||||
|
elif choice == '5':
|
||||||
|
delete_project()
|
||||||
|
elif choice == '6':
|
||||||
|
exit()
|
||||||
|
else:
|
||||||
|
print("Invalid choice. Please enter 1, 2, 3, or 4.")
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
@ -0,0 +1,247 @@
|
|||||||
|
<#
|
||||||
|
.Synopsis
|
||||||
|
Activate a Python virtual environment for the current PowerShell session.
|
||||||
|
|
||||||
|
.Description
|
||||||
|
Pushes the python executable for a virtual environment to the front of the
|
||||||
|
$Env:PATH environment variable and sets the prompt to signify that you are
|
||||||
|
in a Python virtual environment. Makes use of the command line switches as
|
||||||
|
well as the `pyvenv.cfg` file values present in the virtual environment.
|
||||||
|
|
||||||
|
.Parameter VenvDir
|
||||||
|
Path to the directory that contains the virtual environment to activate. The
|
||||||
|
default value for this is the parent of the directory that the Activate.ps1
|
||||||
|
script is located within.
|
||||||
|
|
||||||
|
.Parameter Prompt
|
||||||
|
The prompt prefix to display when this virtual environment is activated. By
|
||||||
|
default, this prompt is the name of the virtual environment folder (VenvDir)
|
||||||
|
surrounded by parentheses and followed by a single space (ie. '(.venv) ').
|
||||||
|
|
||||||
|
.Example
|
||||||
|
Activate.ps1
|
||||||
|
Activates the Python virtual environment that contains the Activate.ps1 script.
|
||||||
|
|
||||||
|
.Example
|
||||||
|
Activate.ps1 -Verbose
|
||||||
|
Activates the Python virtual environment that contains the Activate.ps1 script,
|
||||||
|
and shows extra information about the activation as it executes.
|
||||||
|
|
||||||
|
.Example
|
||||||
|
Activate.ps1 -VenvDir C:\Users\MyUser\Common\.venv
|
||||||
|
Activates the Python virtual environment located in the specified location.
|
||||||
|
|
||||||
|
.Example
|
||||||
|
Activate.ps1 -Prompt "MyPython"
|
||||||
|
Activates the Python virtual environment that contains the Activate.ps1 script,
|
||||||
|
and prefixes the current prompt with the specified string (surrounded in
|
||||||
|
parentheses) while the virtual environment is active.
|
||||||
|
|
||||||
|
.Notes
|
||||||
|
On Windows, it may be required to enable this Activate.ps1 script by setting the
|
||||||
|
execution policy for the user. You can do this by issuing the following PowerShell
|
||||||
|
command:
|
||||||
|
|
||||||
|
PS C:\> Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
|
||||||
|
|
||||||
|
For more information on Execution Policies:
|
||||||
|
https://go.microsoft.com/fwlink/?LinkID=135170
|
||||||
|
|
||||||
|
#>
|
||||||
|
Param(
|
||||||
|
[Parameter(Mandatory = $false)]
|
||||||
|
[String]
|
||||||
|
$VenvDir,
|
||||||
|
[Parameter(Mandatory = $false)]
|
||||||
|
[String]
|
||||||
|
$Prompt
|
||||||
|
)
|
||||||
|
|
||||||
|
<# Function declarations --------------------------------------------------- #>
|
||||||
|
|
||||||
|
<#
|
||||||
|
.Synopsis
|
||||||
|
Remove all shell session elements added by the Activate script, including the
|
||||||
|
addition of the virtual environment's Python executable from the beginning of
|
||||||
|
the PATH variable.
|
||||||
|
|
||||||
|
.Parameter NonDestructive
|
||||||
|
If present, do not remove this function from the global namespace for the
|
||||||
|
session.
|
||||||
|
|
||||||
|
#>
|
||||||
|
function global:deactivate ([switch]$NonDestructive) {
|
||||||
|
# Revert to original values
|
||||||
|
|
||||||
|
# The prior prompt:
|
||||||
|
if (Test-Path -Path Function:_OLD_VIRTUAL_PROMPT) {
|
||||||
|
Copy-Item -Path Function:_OLD_VIRTUAL_PROMPT -Destination Function:prompt
|
||||||
|
Remove-Item -Path Function:_OLD_VIRTUAL_PROMPT
|
||||||
|
}
|
||||||
|
|
||||||
|
# The prior PYTHONHOME:
|
||||||
|
if (Test-Path -Path Env:_OLD_VIRTUAL_PYTHONHOME) {
|
||||||
|
Copy-Item -Path Env:_OLD_VIRTUAL_PYTHONHOME -Destination Env:PYTHONHOME
|
||||||
|
Remove-Item -Path Env:_OLD_VIRTUAL_PYTHONHOME
|
||||||
|
}
|
||||||
|
|
||||||
|
# The prior PATH:
|
||||||
|
if (Test-Path -Path Env:_OLD_VIRTUAL_PATH) {
|
||||||
|
Copy-Item -Path Env:_OLD_VIRTUAL_PATH -Destination Env:PATH
|
||||||
|
Remove-Item -Path Env:_OLD_VIRTUAL_PATH
|
||||||
|
}
|
||||||
|
|
||||||
|
# Just remove the VIRTUAL_ENV altogether:
|
||||||
|
if (Test-Path -Path Env:VIRTUAL_ENV) {
|
||||||
|
Remove-Item -Path env:VIRTUAL_ENV
|
||||||
|
}
|
||||||
|
|
||||||
|
# Just remove VIRTUAL_ENV_PROMPT altogether.
|
||||||
|
if (Test-Path -Path Env:VIRTUAL_ENV_PROMPT) {
|
||||||
|
Remove-Item -Path env:VIRTUAL_ENV_PROMPT
|
||||||
|
}
|
||||||
|
|
||||||
|
# Just remove the _PYTHON_VENV_PROMPT_PREFIX altogether:
|
||||||
|
if (Get-Variable -Name "_PYTHON_VENV_PROMPT_PREFIX" -ErrorAction SilentlyContinue) {
|
||||||
|
Remove-Variable -Name _PYTHON_VENV_PROMPT_PREFIX -Scope Global -Force
|
||||||
|
}
|
||||||
|
|
||||||
|
# Leave deactivate function in the global namespace if requested:
|
||||||
|
if (-not $NonDestructive) {
|
||||||
|
Remove-Item -Path function:deactivate
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
<#
|
||||||
|
.Description
|
||||||
|
Get-PyVenvConfig parses the values from the pyvenv.cfg file located in the
|
||||||
|
given folder, and returns them in a map.
|
||||||
|
|
||||||
|
For each line in the pyvenv.cfg file, if that line can be parsed into exactly
|
||||||
|
two strings separated by `=` (with any amount of whitespace surrounding the =)
|
||||||
|
then it is considered a `key = value` line. The left hand string is the key,
|
||||||
|
the right hand is the value.
|
||||||
|
|
||||||
|
If the value starts with a `'` or a `"` then the first and last character is
|
||||||
|
stripped from the value before being captured.
|
||||||
|
|
||||||
|
.Parameter ConfigDir
|
||||||
|
Path to the directory that contains the `pyvenv.cfg` file.
|
||||||
|
#>
|
||||||
|
function Get-PyVenvConfig(
|
||||||
|
[String]
|
||||||
|
$ConfigDir
|
||||||
|
) {
|
||||||
|
Write-Verbose "Given ConfigDir=$ConfigDir, obtain values in pyvenv.cfg"
|
||||||
|
|
||||||
|
# Ensure the file exists, and issue a warning if it doesn't (but still allow the function to continue).
|
||||||
|
$pyvenvConfigPath = Join-Path -Resolve -Path $ConfigDir -ChildPath 'pyvenv.cfg' -ErrorAction Continue
|
||||||
|
|
||||||
|
# An empty map will be returned if no config file is found.
|
||||||
|
$pyvenvConfig = @{ }
|
||||||
|
|
||||||
|
if ($pyvenvConfigPath) {
|
||||||
|
|
||||||
|
Write-Verbose "File exists, parse `key = value` lines"
|
||||||
|
$pyvenvConfigContent = Get-Content -Path $pyvenvConfigPath
|
||||||
|
|
||||||
|
$pyvenvConfigContent | ForEach-Object {
|
||||||
|
$keyval = $PSItem -split "\s*=\s*", 2
|
||||||
|
if ($keyval[0] -and $keyval[1]) {
|
||||||
|
$val = $keyval[1]
|
||||||
|
|
||||||
|
# Remove extraneous quotations around a string value.
|
||||||
|
if ("'""".Contains($val.Substring(0, 1))) {
|
||||||
|
$val = $val.Substring(1, $val.Length - 2)
|
||||||
|
}
|
||||||
|
|
||||||
|
$pyvenvConfig[$keyval[0]] = $val
|
||||||
|
Write-Verbose "Adding Key: '$($keyval[0])'='$val'"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $pyvenvConfig
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
<# Begin Activate script --------------------------------------------------- #>
|
||||||
|
|
||||||
|
# Determine the containing directory of this script
|
||||||
|
$VenvExecPath = Split-Path -Parent $MyInvocation.MyCommand.Definition
|
||||||
|
$VenvExecDir = Get-Item -Path $VenvExecPath
|
||||||
|
|
||||||
|
Write-Verbose "Activation script is located in path: '$VenvExecPath'"
|
||||||
|
Write-Verbose "VenvExecDir Fullname: '$($VenvExecDir.FullName)"
|
||||||
|
Write-Verbose "VenvExecDir Name: '$($VenvExecDir.Name)"
|
||||||
|
|
||||||
|
# Set values required in priority: CmdLine, ConfigFile, Default
|
||||||
|
# First, get the location of the virtual environment, it might not be
|
||||||
|
# VenvExecDir if specified on the command line.
|
||||||
|
if ($VenvDir) {
|
||||||
|
Write-Verbose "VenvDir given as parameter, using '$VenvDir' to determine values"
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Write-Verbose "VenvDir not given as a parameter, using parent directory name as VenvDir."
|
||||||
|
$VenvDir = $VenvExecDir.Parent.FullName.TrimEnd("\\/")
|
||||||
|
Write-Verbose "VenvDir=$VenvDir"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Next, read the `pyvenv.cfg` file to determine any required value such
|
||||||
|
# as `prompt`.
|
||||||
|
$pyvenvCfg = Get-PyVenvConfig -ConfigDir $VenvDir
|
||||||
|
|
||||||
|
# Next, set the prompt from the command line, or the config file, or
|
||||||
|
# just use the name of the virtual environment folder.
|
||||||
|
if ($Prompt) {
|
||||||
|
Write-Verbose "Prompt specified as argument, using '$Prompt'"
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Write-Verbose "Prompt not specified as argument to script, checking pyvenv.cfg value"
|
||||||
|
if ($pyvenvCfg -and $pyvenvCfg['prompt']) {
|
||||||
|
Write-Verbose " Setting based on value in pyvenv.cfg='$($pyvenvCfg['prompt'])'"
|
||||||
|
$Prompt = $pyvenvCfg['prompt'];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Write-Verbose " Setting prompt based on parent's directory's name. (Is the directory name passed to venv module when creating the virtual environment)"
|
||||||
|
Write-Verbose " Got leaf-name of $VenvDir='$(Split-Path -Path $venvDir -Leaf)'"
|
||||||
|
$Prompt = Split-Path -Path $venvDir -Leaf
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Verbose "Prompt = '$Prompt'"
|
||||||
|
Write-Verbose "VenvDir='$VenvDir'"
|
||||||
|
|
||||||
|
# Deactivate any currently active virtual environment, but leave the
|
||||||
|
# deactivate function in place.
|
||||||
|
deactivate -nondestructive
|
||||||
|
|
||||||
|
# Now set the environment variable VIRTUAL_ENV, used by many tools to determine
|
||||||
|
# that there is an activated venv.
|
||||||
|
$env:VIRTUAL_ENV = $VenvDir
|
||||||
|
|
||||||
|
if (-not $Env:VIRTUAL_ENV_DISABLE_PROMPT) {
|
||||||
|
|
||||||
|
Write-Verbose "Setting prompt to '$Prompt'"
|
||||||
|
|
||||||
|
# Set the prompt to include the env name
|
||||||
|
# Make sure _OLD_VIRTUAL_PROMPT is global
|
||||||
|
function global:_OLD_VIRTUAL_PROMPT { "" }
|
||||||
|
Copy-Item -Path function:prompt -Destination function:_OLD_VIRTUAL_PROMPT
|
||||||
|
New-Variable -Name _PYTHON_VENV_PROMPT_PREFIX -Description "Python virtual environment prompt prefix" -Scope Global -Option ReadOnly -Visibility Public -Value $Prompt
|
||||||
|
|
||||||
|
function global:prompt {
|
||||||
|
Write-Host -NoNewline -ForegroundColor Green "($_PYTHON_VENV_PROMPT_PREFIX) "
|
||||||
|
_OLD_VIRTUAL_PROMPT
|
||||||
|
}
|
||||||
|
$env:VIRTUAL_ENV_PROMPT = $Prompt
|
||||||
|
}
|
||||||
|
|
||||||
|
# Clear PYTHONHOME
|
||||||
|
if (Test-Path -Path Env:PYTHONHOME) {
|
||||||
|
Copy-Item -Path Env:PYTHONHOME -Destination Env:_OLD_VIRTUAL_PYTHONHOME
|
||||||
|
Remove-Item -Path Env:PYTHONHOME
|
||||||
|
}
|
||||||
|
|
||||||
|
# Add the venv to the PATH
|
||||||
|
Copy-Item -Path Env:PATH -Destination Env:_OLD_VIRTUAL_PATH
|
||||||
|
$Env:PATH = "$VenvExecDir$([System.IO.Path]::PathSeparator)$Env:PATH"
|
@ -0,0 +1,70 @@
|
|||||||
|
# This file must be used with "source bin/activate" *from bash*
|
||||||
|
# You cannot run it directly
|
||||||
|
|
||||||
|
deactivate () {
|
||||||
|
# reset old environment variables
|
||||||
|
if [ -n "${_OLD_VIRTUAL_PATH:-}" ] ; then
|
||||||
|
PATH="${_OLD_VIRTUAL_PATH:-}"
|
||||||
|
export PATH
|
||||||
|
unset _OLD_VIRTUAL_PATH
|
||||||
|
fi
|
||||||
|
if [ -n "${_OLD_VIRTUAL_PYTHONHOME:-}" ] ; then
|
||||||
|
PYTHONHOME="${_OLD_VIRTUAL_PYTHONHOME:-}"
|
||||||
|
export PYTHONHOME
|
||||||
|
unset _OLD_VIRTUAL_PYTHONHOME
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Call hash to forget past commands. Without forgetting
|
||||||
|
# past commands the $PATH changes we made may not be respected
|
||||||
|
hash -r 2> /dev/null
|
||||||
|
|
||||||
|
if [ -n "${_OLD_VIRTUAL_PS1:-}" ] ; then
|
||||||
|
PS1="${_OLD_VIRTUAL_PS1:-}"
|
||||||
|
export PS1
|
||||||
|
unset _OLD_VIRTUAL_PS1
|
||||||
|
fi
|
||||||
|
|
||||||
|
unset VIRTUAL_ENV
|
||||||
|
unset VIRTUAL_ENV_PROMPT
|
||||||
|
if [ ! "${1:-}" = "nondestructive" ] ; then
|
||||||
|
# Self destruct!
|
||||||
|
unset -f deactivate
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# unset irrelevant variables
|
||||||
|
deactivate nondestructive
|
||||||
|
|
||||||
|
# on Windows, a path can contain colons and backslashes and has to be converted:
|
||||||
|
if [ "${OSTYPE:-}" = "cygwin" ] || [ "${OSTYPE:-}" = "msys" ] ; then
|
||||||
|
# transform D:\path\to\venv to /d/path/to/venv on MSYS
|
||||||
|
# and to /cygdrive/d/path/to/venv on Cygwin
|
||||||
|
export VIRTUAL_ENV=$(cygpath "/Users/poni/lorenzo-web/script")
|
||||||
|
else
|
||||||
|
# use the path as-is
|
||||||
|
export VIRTUAL_ENV="/Users/poni/lorenzo-web/script"
|
||||||
|
fi
|
||||||
|
|
||||||
|
_OLD_VIRTUAL_PATH="$PATH"
|
||||||
|
PATH="$VIRTUAL_ENV/bin:$PATH"
|
||||||
|
export PATH
|
||||||
|
|
||||||
|
# unset PYTHONHOME if set
|
||||||
|
# this will fail if PYTHONHOME is set to the empty string (which is bad anyway)
|
||||||
|
# could use `if (set -u; : $PYTHONHOME) ;` in bash
|
||||||
|
if [ -n "${PYTHONHOME:-}" ] ; then
|
||||||
|
_OLD_VIRTUAL_PYTHONHOME="${PYTHONHOME:-}"
|
||||||
|
unset PYTHONHOME
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "${VIRTUAL_ENV_DISABLE_PROMPT:-}" ] ; then
|
||||||
|
_OLD_VIRTUAL_PS1="${PS1:-}"
|
||||||
|
PS1="(script) ${PS1:-}"
|
||||||
|
export PS1
|
||||||
|
VIRTUAL_ENV_PROMPT="(script) "
|
||||||
|
export VIRTUAL_ENV_PROMPT
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Call hash to forget past commands. Without forgetting
|
||||||
|
# past commands the $PATH changes we made may not be respected
|
||||||
|
hash -r 2> /dev/null
|
@ -0,0 +1,27 @@
|
|||||||
|
# This file must be used with "source bin/activate.csh" *from csh*.
|
||||||
|
# You cannot run it directly.
|
||||||
|
|
||||||
|
# Created by Davide Di Blasi <davidedb@gmail.com>.
|
||||||
|
# Ported to Python 3.3 venv by Andrew Svetlov <andrew.svetlov@gmail.com>
|
||||||
|
|
||||||
|
alias deactivate 'test $?_OLD_VIRTUAL_PATH != 0 && setenv PATH "$_OLD_VIRTUAL_PATH" && unset _OLD_VIRTUAL_PATH; rehash; test $?_OLD_VIRTUAL_PROMPT != 0 && set prompt="$_OLD_VIRTUAL_PROMPT" && unset _OLD_VIRTUAL_PROMPT; unsetenv VIRTUAL_ENV; unsetenv VIRTUAL_ENV_PROMPT; test "\!:*" != "nondestructive" && unalias deactivate'
|
||||||
|
|
||||||
|
# Unset irrelevant variables.
|
||||||
|
deactivate nondestructive
|
||||||
|
|
||||||
|
setenv VIRTUAL_ENV "/Users/poni/lorenzo-web/script"
|
||||||
|
|
||||||
|
set _OLD_VIRTUAL_PATH="$PATH"
|
||||||
|
setenv PATH "$VIRTUAL_ENV/bin:$PATH"
|
||||||
|
|
||||||
|
|
||||||
|
set _OLD_VIRTUAL_PROMPT="$prompt"
|
||||||
|
|
||||||
|
if (! "$?VIRTUAL_ENV_DISABLE_PROMPT") then
|
||||||
|
set prompt = "(script) $prompt"
|
||||||
|
setenv VIRTUAL_ENV_PROMPT "(script) "
|
||||||
|
endif
|
||||||
|
|
||||||
|
alias pydoc python -m pydoc
|
||||||
|
|
||||||
|
rehash
|
@ -0,0 +1,69 @@
|
|||||||
|
# This file must be used with "source <venv>/bin/activate.fish" *from fish*
|
||||||
|
# (https://fishshell.com/). You cannot run it directly.
|
||||||
|
|
||||||
|
function deactivate -d "Exit virtual environment and return to normal shell environment"
|
||||||
|
# reset old environment variables
|
||||||
|
if test -n "$_OLD_VIRTUAL_PATH"
|
||||||
|
set -gx PATH $_OLD_VIRTUAL_PATH
|
||||||
|
set -e _OLD_VIRTUAL_PATH
|
||||||
|
end
|
||||||
|
if test -n "$_OLD_VIRTUAL_PYTHONHOME"
|
||||||
|
set -gx PYTHONHOME $_OLD_VIRTUAL_PYTHONHOME
|
||||||
|
set -e _OLD_VIRTUAL_PYTHONHOME
|
||||||
|
end
|
||||||
|
|
||||||
|
if test -n "$_OLD_FISH_PROMPT_OVERRIDE"
|
||||||
|
set -e _OLD_FISH_PROMPT_OVERRIDE
|
||||||
|
# prevents error when using nested fish instances (Issue #93858)
|
||||||
|
if functions -q _old_fish_prompt
|
||||||
|
functions -e fish_prompt
|
||||||
|
functions -c _old_fish_prompt fish_prompt
|
||||||
|
functions -e _old_fish_prompt
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
set -e VIRTUAL_ENV
|
||||||
|
set -e VIRTUAL_ENV_PROMPT
|
||||||
|
if test "$argv[1]" != "nondestructive"
|
||||||
|
# Self-destruct!
|
||||||
|
functions -e deactivate
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Unset irrelevant variables.
|
||||||
|
deactivate nondestructive
|
||||||
|
|
||||||
|
set -gx VIRTUAL_ENV "/Users/poni/lorenzo-web/script"
|
||||||
|
|
||||||
|
set -gx _OLD_VIRTUAL_PATH $PATH
|
||||||
|
set -gx PATH "$VIRTUAL_ENV/bin" $PATH
|
||||||
|
|
||||||
|
# Unset PYTHONHOME if set.
|
||||||
|
if set -q PYTHONHOME
|
||||||
|
set -gx _OLD_VIRTUAL_PYTHONHOME $PYTHONHOME
|
||||||
|
set -e PYTHONHOME
|
||||||
|
end
|
||||||
|
|
||||||
|
if test -z "$VIRTUAL_ENV_DISABLE_PROMPT"
|
||||||
|
# fish uses a function instead of an env var to generate the prompt.
|
||||||
|
|
||||||
|
# Save the current fish_prompt function as the function _old_fish_prompt.
|
||||||
|
functions -c fish_prompt _old_fish_prompt
|
||||||
|
|
||||||
|
# With the original prompt function renamed, we can override with our own.
|
||||||
|
function fish_prompt
|
||||||
|
# Save the return status of the last command.
|
||||||
|
set -l old_status $status
|
||||||
|
|
||||||
|
# Output the venv prompt; color taken from the blue of the Python logo.
|
||||||
|
printf "%s%s%s" (set_color 4B8BBE) "(script) " (set_color normal)
|
||||||
|
|
||||||
|
# Restore the return status of the previous command.
|
||||||
|
echo "exit $old_status" | .
|
||||||
|
# Output the original/"old" prompt.
|
||||||
|
_old_fish_prompt
|
||||||
|
end
|
||||||
|
|
||||||
|
set -gx _OLD_FISH_PROMPT_OVERRIDE "$VIRTUAL_ENV"
|
||||||
|
set -gx VIRTUAL_ENV_PROMPT "(script) "
|
||||||
|
end
|
@ -0,0 +1,8 @@
|
|||||||
|
#!/Users/poni/lorenzo-web/script/bin/python3.12
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
import re
|
||||||
|
import sys
|
||||||
|
from markdown.__main__ import run
|
||||||
|
if __name__ == '__main__':
|
||||||
|
sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
|
||||||
|
sys.exit(run())
|
@ -0,0 +1,8 @@
|
|||||||
|
#!/Users/poni/lorenzo-web/script/bin/python3.12
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
import re
|
||||||
|
import sys
|
||||||
|
from pip._internal.cli.main import main
|
||||||
|
if __name__ == '__main__':
|
||||||
|
sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
|
||||||
|
sys.exit(main())
|
@ -0,0 +1,8 @@
|
|||||||
|
#!/Users/poni/lorenzo-web/script/bin/python3.12
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
import re
|
||||||
|
import sys
|
||||||
|
from pip._internal.cli.main import main
|
||||||
|
if __name__ == '__main__':
|
||||||
|
sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
|
||||||
|
sys.exit(main())
|
@ -0,0 +1,8 @@
|
|||||||
|
#!/Users/poni/lorenzo-web/script/bin/python3.12
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
import re
|
||||||
|
import sys
|
||||||
|
from pip._internal.cli.main import main
|
||||||
|
if __name__ == '__main__':
|
||||||
|
sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
|
||||||
|
sys.exit(main())
|
@ -0,0 +1 @@
|
|||||||
|
python3.12
|
@ -0,0 +1 @@
|
|||||||
|
python3.12
|
@ -0,0 +1 @@
|
|||||||
|
/usr/local/opt/python@3.12/bin/python3.12
|
@ -0,0 +1,208 @@
|
|||||||
|
{
|
||||||
|
"projects": {
|
||||||
|
"confabulazioni": {
|
||||||
|
"name": [
|
||||||
|
"Confabulazioni",
|
||||||
|
"Confabulazioni"
|
||||||
|
],
|
||||||
|
"category": [
|
||||||
|
"Prosa",
|
||||||
|
"Theater"
|
||||||
|
],
|
||||||
|
"main_picture": "Locandina - opzione A.jpg",
|
||||||
|
"captions_it": {
|
||||||
|
"Locandina - opzione B.jpg": "",
|
||||||
|
"4.jpg": "",
|
||||||
|
"5.jpg": "",
|
||||||
|
"7.jpg": "",
|
||||||
|
"6.jpg": "",
|
||||||
|
"2.jpg": "",
|
||||||
|
"3.jpg": "",
|
||||||
|
"1.jpg": ""
|
||||||
|
},
|
||||||
|
"captions_en": {
|
||||||
|
"Locandina - opzione B.jpg": "",
|
||||||
|
"4.jpg": "",
|
||||||
|
"5.jpg": "",
|
||||||
|
"7.jpg": "",
|
||||||
|
"6.jpg": "",
|
||||||
|
"2.jpg": "",
|
||||||
|
"3.jpg": "",
|
||||||
|
"1.jpg": ""
|
||||||
|
},
|
||||||
|
"video_url": "",
|
||||||
|
"html_content_it": "<ul>\n<li>di Eleonora Paris</li>\n<li>regia Lorenzo Ponte</li>\n<li>tutor Michele De Vita Conti</li>\n<li>con Elena Callegari, Alice Conti, Marco Vergani\ne con Sebastiano Bronzato, Chiara Cali\u00f2, Eleonora Paris, Lorenzo Ponte</li>\n<li>musiche dal vivo Sebastiano Bronzato</li>\n<li>adattamento musicale Gabriele Gramaglia, Edoardo Grittini, Gianfranco Pedroli</li>\n<li>scene e costumi Serena D\u2019Orlando, Valentina Silva, Lorenzo Vigevani</li>\n<li>videomaker Chiara Cali\u00f2</li>\n<li>tecnica video Fabio Brusadin</li>\n<li>organizzazione e promozione Simona Conforti, Elisa Piasente, Camilla Rizzi</li>\n<li>Spettacolo inserito nella rassegna teatrale Teste Inedite</li>\n<li>realizzata da autori, registi e organizzatori della Civica Scuola di Teatro Paolo Grassi</li>\n</ul>\n<p><strong>Note di regia</strong></p>\n<p>Confabulazioni di Eleonora Paris \u00e8 una storia di formazione; i personaggi faticano ad affrontare la realt\u00e0, l\u2019inevitabile fine delle cose. Mettono in scena un matrimonio, il pi\u00f9 tradizionale dei riti, per esorcizzare la paura della morte della nonna e fuggire dalla complessit\u00e0 di una relazione d\u2019amore. Verit\u00e0 e menzogna si intrecciano in questo testo, tutto \u00e8 finto, nulla \u00e8 falso. Ognuno dei personaggi ha le sue ragioni per affrontare questo gioco di ruoli, tutti si impegnano affinch\u00e9 la festa riesca al meglio. Dentro i personaggi si agitano segreti e pensieri irrisolti, fuori tutto deve apparire perfetto. In scena musicisti e operatori video affiancano gli attori per costruire l\u2019immagine di un\u2019unione felice. Se all\u2019inizio le regole del gioco sono chiare, procedendo i confini sfumano e il gioco si fa via via pi\u00f9 pericoloso. Lo sforzo continuo di rendere credibile la festa finisce per soggiogare i personaggi alla loro stessa menzogna. In un\u2019epoca in cui l\u2019autenticit\u00e0 e il benessere individuale sono i valori su cui si fonda la nostra societ\u00e0, qual \u00e8 lo stato di salute dei modelli che hanno tentato di assicurarci la felicit\u00e0 di coppia fino ad oggi?</p>\n<p><em>Lorenzo Ponte</em></p>\n<p><strong>Note di drammaturgia</strong></p>\n<p>Due amici d\u2019infanzia si rivedono a un anno di distanza. Lui vive a Londra, lei vive in Italia con sua nonna, una donna molto anziana. Per realizzare il desiderio della nonna di vedere sua nipote sposata prima di morire, i due decidono di organizzare un finto matrimonio. Questa finzione per\u00f2 riapre in loro dei problemi irrisolti e la loro stessa messinscena li spinger\u00e0 a guardarsi veramente e ad affrontare la complessit\u00e0 del loro rapporto. Confabulazioni \u00e8 un testo che parla di solitudine, una condizione che i personaggi vivono con timore ma che al tempo stesso vedono come l\u2019unica possibilit\u00e0 per esprimere la propria libert\u00e0 personale. La paura di non bastare a s\u00e9 stessi e la paura che l\u2019altro limiti la propria indipendenza sono i due poli entro i quali i personaggi si muovono. I loro ricordi si confondono con le narrazioni idealizzate del loro rapporto: se i ricordi creano una storia e questa storia \u00e8 costruita sulle proprie fantasie non si hanno pi\u00f9 parametri per valutare la realt\u00e0. Tutto vale, ma se tutto vale niente ha pi\u00f9 valore. Attraverso questo testo ho cercato di indagare il modo in cui oggi si ridefiniscono i rapporti affettivi e come la paura di perdere l\u2019altro ci impedisca di scoprirlo realmente.</p>\n<p><em>Eleonora Paris</em></p>\n<p>Giugno 2018</p>",
|
||||||
|
"html_content_en": "<ul>\n<li>written by Eleonora Paris</li>\n<li>directed by Lorenzo Ponte</li>\n<li>tutor Michele De Vita Conti</li>\n<li>with Elena Callegari, Alice Conti, Marco Vergani\nand Sebastiano Bronzato, Chiara Cali\u00f2, Eleonora Paris, Lorenzo Ponte</li>\n<li>live music Sebastiano Bronzato</li>\n<li>soundtrack Gabriele Gramaglia, Edoardo Grittini, Gianfranco Pedroli</li>\n<li>set and costume design Serena D\u2019Orlando, Valentina Silva, Lorenzo Vigevani</li>\n<li>videomaker Chiara Cali\u00f2</li>\n<li>video set up Fabio Brusadin</li>\n<li>organization and promotion Simona Conforti, Elisa Piasente, Camilla Rizzi</li>\n<li>Show included in Teste Inedite, Civica Scuola di Teatro Paolo Grassi</li>\n</ul>\n<p><strong>Director's notes</strong></p>\n<p>Confabulazioni by Eleonora Paris is a coming-of-age story; the characters struggle to face reality, the inevitable end of things. They stage a wedding, the most traditional of rites, to exorcise the fear of their grandmother's death and escape from the complexity of a love relationship. Truth and lies are intertwined in this text, everything is fake, nothing is false. Each of the characters has their own reasons for tackling this role play, everyone is committed to making sure the party is as successful as possible. Secrets and unresolved thoughts swirl inside the characters, everything must appear perfect on the outside. On stage, musicians and videographers work alongside the actors to build the image of a happy union. If at the beginning the rules of the game are clear, as the game progresses the boundaries blur and the game gradually becomes more dangerous. The continuous effort to make the party credible ends up subjugating the characters to their own lie. In a society founded on the values of authenticity and individual well-being, what is the state of health of the models who have attempted to ensure the happiness of people?</p>\n<p><em>Lorenzo Ponte</em> </p>\n<p><strong>Notes on dramaturgy</strong></p>\n<p>Two childhood friends meet again a year later. He lives in London, she lives in Italy with her grandmother, a very old woman. To fulfill the grandmother's wish to see her granddaughter married before she dies, the two decide to organize a fake wedding. This fiction, however, reopens unresolved problems in them and their very staging will push them to really look at each other and face the complexity of their relationship. Confabulazioni is a text that talks about loneliness, a condition that the characters live with fear but at the same time see as the only possibility to express their personal freedom. The fear of not being enough for oneself and the fear that others will limit one's independence are the two poles within which the characters move. Their memories become confused with the idealized narratives of their relationship: if the memories create a story and this story is built on one's fantasies, one no longer has parameters to evaluate reality. Everything is valid, but if everything is valid nothing has value anymore.\nThrough this text I tried to investigate the way in which emotional relationships are redefined today and how the fear of losing the other prevents us from truly discovering it.</p>\n<p><em>Eleonora Paris</em></p>\n<p>June 2018</p>"
|
||||||
|
},
|
||||||
|
"tu_sei_agatha": {
|
||||||
|
"name": [
|
||||||
|
"Tu Sei Agatha",
|
||||||
|
"You Are Agatha"
|
||||||
|
],
|
||||||
|
"category": [
|
||||||
|
"Prosa",
|
||||||
|
"Theater"
|
||||||
|
],
|
||||||
|
"main_picture": "A - Locandina.png",
|
||||||
|
"captions_it": {},
|
||||||
|
"captions_en": {},
|
||||||
|
"video_url": "<iframe src='https://player.vimeo.com/video/219024393?h=83c62b88eb&title=0&byline=0&portrait=0' frameborder='0' allow='autoplay; fullscreen; picture-in-picture' allowfullscreen></iframe><script src='https://player.vimeo.com/api/player.js'></script>",
|
||||||
|
"html_content_it": "<ul>\n<li>da Agatha di Marguerite Duras</li>\n<li>adattamento e regia Lorenzo Ponte</li>\n<li>con Christian La Rosa e Valentina Picello</li>\n<li>scena Davide Signorini</li>\n<li>musica Sebastiano Bronzato</li>\n<li>luci Giuliano Almerighi</li>\n<li>Foto Luca de Pia</li>\n<li>produzione Teatro Franco Parenti</li>\n</ul>\n<p>Si ringraziano Sabrina Sinatti, tutor del progetto - Civica Scuola di Teatro Paolo Grassi - e Lab121.\nSi ringrazia per la collaborazione VIE dei festival - Roma e la rassegna Stanze, per cui lo spettacolo \u00e8 andato in scena a Palazzo Boschi Di Stefano.</p>\n<p>Esistono legami che niente \u00e8 in grado di scalfire. Tu sei Agatha d\u00e0 forma poetica a un\nmistero irrappresentabile: l'amore disperato e impossibile tra un fratello e una sorella. Tra\nle righe del testo si legge velata la bruciante autobiografia di Marguerite Duras, del suo\namore per il fratello Paulo morto giovane e dei suoi ricordi.</p>\n<p>Nella villa d'infanzia, ormai abbandonata, Agata, incontra il fratello che non vede da anni.\nHa deciso di partire e interrompere il rapporto incestuoso che li unisce; ha incontrato un\nuomo e andr\u00e0 a vivere con lui ma la possibilit\u00e0 di una separazione fa riemergere ricordi,\nnodi di un legame, difficili da sciogliere. Il loro rapporto incestuoso e indissolubile \u00e8 uno\nspecchio rovesciato che riflette la nostra difficolt\u00e0 ad incontrare ed accettare la libert\u00e0\ndell'Altro e il dolore del fallimento.</p>\n<p>La scena \u00e8 vuota per fare spazio a un rito d'incontro tra due corpi che si sono sempre\ncercati senza mai toccarsi. Lo spazio teatrale diventa il luogo ideale per indagare il cuore\ndella relazione e liberare quel feroce desiderio a lungo frustrato.</p>\n<p><em>Tu sei Agatha</em> \u00e8 la storia di un amore e del tentativo di sopravvivere alla sua forza.</p>\n<p>Ottobre 2018</p>",
|
||||||
|
"html_content_en": "<ul>\n<li>from Agatha by Marguerite Duras</li>\n<li>dramaturgy and direction Lorenzo Ponte</li>\n<li>with Christian La Rosa and Valentina Picello</li>\n<li>set design Davide Signorini</li>\n<li>music Sebastiano Bronzato</li>\n<li>light design Giuliano Almerighi</li>\n<li>Pictures by Luca Del Pia</li>\n<li>Production Teatro Franco parenti</li>\n</ul>\n<p>Thanks to Sabrina Sinatti, project tutor - Civica Scuola di Teatro Paolo Grassi - Lab121 - VIE dei Festival, Rome - Stanze, Milan</p>\n<p>There are bonds that nothing can undermine. You are Agatha gives poetic form to an\nunrepresentable mystery: the desperate and impossible love between a brother and a\nsister. Hidden in this fictional story there is of course the burning autobiography of\nMarguerite Duras and the memory of her love for her brother Paulo who died when he was\nan adolescent.</p>\n<p>In her childhood villa, now abandoned, Agatha meets her brother. She has decided to\nleave and interrupt the incestuous relationship that unites them; she has met a man and\nwill go to live with him. However the impending separation brings back memories, which\nare not fading away. Their incestuous and indissoluble relationship is an inverted mirror\nthat reflects our difficulty in meeting and accepting the freedom of the Other and the pain\nof failure.</p>\n<p>The stage is empty in order to host a ritual between two bodies that have always looked\nfor each other without being able to touch. Theater becomes the ideal place to investigate\nthe heart of the relationship and release that ferocious desire that has long been\nfrustrated.</p>\n<p><em>Tu sei Agatha</em> is the story of a love and the attempt to survive its strength.</p>\n<p>October 2018</p>"
|
||||||
|
},
|
||||||
|
"buoni_a_nulla": {
|
||||||
|
"name": [
|
||||||
|
"Buoni a Nulla",
|
||||||
|
"Good for Nothing"
|
||||||
|
],
|
||||||
|
"category": [
|
||||||
|
"Prosa",
|
||||||
|
"Theater"
|
||||||
|
],
|
||||||
|
"main_picture": "Locandina.JPG",
|
||||||
|
"captions_it": {
|
||||||
|
"6c.JPG": "",
|
||||||
|
"6b.JPG": "",
|
||||||
|
"8.JPG": "",
|
||||||
|
"9.JPG": "",
|
||||||
|
"1a.JPG": "",
|
||||||
|
"10.JPG": "",
|
||||||
|
"2b.JPG": "",
|
||||||
|
"4.JPG": "",
|
||||||
|
"5.JPG": "",
|
||||||
|
"7.JPG": "",
|
||||||
|
"6.JPG": "",
|
||||||
|
"2.JPG": "",
|
||||||
|
"1.JPG": ""
|
||||||
|
},
|
||||||
|
"captions_en": {
|
||||||
|
"6c.JPG": "",
|
||||||
|
"6b.JPG": "",
|
||||||
|
"8.JPG": "",
|
||||||
|
"9.JPG": "",
|
||||||
|
"1a.JPG": "",
|
||||||
|
"10.JPG": "",
|
||||||
|
"2b.JPG": "",
|
||||||
|
"4.JPG": "",
|
||||||
|
"5.JPG": "",
|
||||||
|
"7.JPG": "",
|
||||||
|
"6.JPG": "",
|
||||||
|
"2.JPG": "",
|
||||||
|
"1.JPG": ""
|
||||||
|
},
|
||||||
|
"video_url": "",
|
||||||
|
"html_content_it": "<ul>\n<li>testo e regia Lorenzo Ponte</li>\n<li>con Tobia Dal Corso Polzot, Paola Galassi e Luca Oldani</li>\n<li>scena Davide Signorini</li>\n<li>costumi Giulia Rossena</li>\n<li>luci Emanuele Agliati</li>\n<li>suono Gaetano Pappalardo e Simone Sigurani</li>\n<li>assistente regia Filippo Capobianco</li>\n<li>voce giornale radio Pietro Adami</li>\n<li>con la supervisione artistica di Giuliana Musso</li>\n<li>Foto di Luca Del Pia</li>\n<li>produzione Teatro Franco Parenti</li>\n</ul>\n<p>con il sostegno di PRAXIS - Olinda/TeatroLaCucina - Vincitore bando Animali Teatrali Fantastici 2021 - ZONA K nell'ambito del progetto IntercettAzioni - Centro di Residenza Artistica della Lombardia; Fondazione Claudia Lombardi per il teatro</p>\n<p>Osservare e stare ai margini per capire cosa sta al centro della nostra societa.\nGuidati da questa idea, per 3 anni abbiamo fatto un percorso di conoscenza e\navvicinamento alla vita delle persone senza dimora nella citt\u00e0 di Milano. Tra il 2019\ne il 2021, la compagnia ha affiancato unit\u00e0 di strade composte da psicologi,\neducatori e volontari che lavorano con persone che vivono questo fenomeno di\nespulsione.</p>\n<p>I nostri pregiudizi sono andati in frantumi e, visti da vicino, abbiamo trovato molti\npunti di contatto con persone che tendiamo a nascondere e cacciare dalle vie delle\nnostre citt\u00e0. I poveri oggi vengono invisibilizzati e stigmatizzati perch\u00e9 costringono a\nfare i conti con le storture e i limiti di citt\u00e0 sempre pi\u00f9 esclusive e respingenti.</p>\n<p>Dalla ricerca \u00e8 scaturito uno spettacolo di narrazione nel quale si incarnano le voci,\ni silenzi, i corpi e le emozioni attraversate sul campo.\nSiamo alla fermata di un autobus che non sappiamo se passer\u00e0 mai. Lo aspettiamo\ninsieme a tre personaggi le cui vicende intrecciandosi raccontano come un prisma\nla marginalit\u00e0 interiore e sociale di Milano. Un giovane studente universitario della\nBocconi, alle prese con gli ultimi esami prima della laurea. Una giornalista precaria\ndi 30 anni, affaticata dai ritmi cittadini, che ha deciso di fare volontariato con le\npersone senza dimora. E infine uno strambo profeta, che maledice la follia che\ndomina la citt\u00e0 e offre a tutti una via di salvezza.</p>\n<p>Con lo spettacolo vogliamo riportare al centro la vita di chi sta ai margini provando\na mettere in discussione lo sguardo pietistico e di superiorit\u00e0 che riserviamo ai devianti. La voce e il vissuto degli ultimi ci interpellano: come ci poniamo di fronte al\ndolore dell'altro? E noi, i sani, come stiamo? E adesso, ancora, che fare?</p>",
|
||||||
|
"html_content_en": "<ul>\n<li>written and directed by Lorenzo Ponte</li>\n<li>with Tobia Dal Corso Polzot, Paola Galassi and Luca Oldani</li>\n<li>set design Davide Signorini</li>\n<li>costumes Giulia Rossena</li>\n<li>lights Emanuele Agliati</li>\n<li>sound design Gaetano Pappalardo and Simone Sigurani</li>\n<li>assistant director Filippo Capobianco,</li>\n<li>radio newspaper voice Pietro Adami</li>\n<li>with the artistic supervision of Giuliana Musso</li>\n<li>Pictures by Foto di Luca Del Pia</li>\n<li>production Teatro Franco Parenti </li>\n</ul>\n<p>with the support of PRAXIS - Olinda/TeatroLaCucina - Winner of the Fantastic Theatrical Animals 2021 ZONA K tender as part of the IntercettAzioni project - Lombardy Artistic Residency Centre; Claudia\nLombardi Foundation for the theatre</p>\n<p>Observe and stay on the margins to understand what is at the center of our society.\nGuided by this idea, for 3 years we have undertaken a journey of understanding\nand approaching people's lives homeless in the city of Milan. Between 2019 and\n2021, the company joined psychologists, educators and volunteers who work with\npeople experiencing this phenomenon of expulsion. </p>\n<p>The research method was\ndivided into three different moments. A first part of participatory observation, in\nwhich the whole company accompanied the road units for a long period on night\noutings in the downtown streets. This work has allowed us to build relationships of\ntrust. The second part of the research consisted of going into the street to talk to\npeople without being framed voluntary associations, to try to distance themselves\nfrom a volunteer-assisted relationship. Finally, where possible, we conducted\ninterviews with homeless people, workers and volunteers and experts to try to build\na broader framework that would allow us to read homelessness as a social\nphenomenon and not as individual problem. Our prejudices were shattered and,\nseen up close, we found many points of contact with people who we tend to hide\nand chase from the streets of our cities. The poor today are invisibilized and\nstigmatized because they force us to deal with the distortions and limitations of\nincreasingly exclusive and repelling cities.</p>\n<p>From the research described above, a narrative show emerged in which voices,\nsilences, bodies and the emotions experienced on the field. We are at the stop of a bus that we don't know if it will ever pass. We wait for him together with three\ncharacters whose intertwining events tell like a prism the internal and social\nmarginality of Milan. A young Bocconi student, struggling with the last exams before\ngraduation. A 30-year-old precarious journalist, tired by the city's rhythms, she\ndecided to volunteer with homeless people. And finally a weirdo prophet, who\ncurses the madness that dominates the city and offers everyone a way of salvation.</p>\n<p>With the show we want to bring the life of those on the margins back to the center\nby trying to question the pietistic and superior look that we reserve for deviants. The\nvoice and experiences of the last challenge us: how do we do we face the pain of\nthe other? And how are we, the healthy ones? And now, what can we do?</p>"
|
||||||
|
},
|
||||||
|
"quando_non_saremo_grandi": {
|
||||||
|
"name": [
|
||||||
|
"Quando non saremo grandi",
|
||||||
|
"Once we won't be great"
|
||||||
|
],
|
||||||
|
"category": [
|
||||||
|
"Prosa",
|
||||||
|
"Theater"
|
||||||
|
],
|
||||||
|
"main_picture": "Immagine locandina copia.jpeg",
|
||||||
|
"captions_it": {
|
||||||
|
"5 copia.jpg": "",
|
||||||
|
".DS_Store": "",
|
||||||
|
"3 copia.jpg": "",
|
||||||
|
"4 copia.jpg": "",
|
||||||
|
"2 copia.jpg": "",
|
||||||
|
"7 copia.jpg": "",
|
||||||
|
"1 copia.jpg": "",
|
||||||
|
"6 copia.jpg": ""
|
||||||
|
},
|
||||||
|
"captions_en": {
|
||||||
|
"5 copia.jpg": "",
|
||||||
|
".DS_Store": "",
|
||||||
|
"3 copia.jpg": "",
|
||||||
|
"4 copia.jpg": "",
|
||||||
|
"2 copia.jpg": "",
|
||||||
|
"7 copia.jpg": "",
|
||||||
|
"1 copia.jpg": "",
|
||||||
|
"6 copia.jpg": ""
|
||||||
|
},
|
||||||
|
"video_url": "<iframe src='https://www.youtube-nocookie.com/embed/BvKjANlXRMc?si=5bgDtodbD7bAmQWg' title='YouTube video player' frameborder='0' allow='accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share' referrerpolicy='strict-origin-when-cross-origin' allowfullscreen></iframe>",
|
||||||
|
"html_content_it": "<ul>\n<li>soggetto Giulia Lombezzi e Lorenzo Ponte</li>\n<li>drammaturgia Giulia Lombezzi</li>\n<li>con llaria Marchian\u00f2, Elia Galeotti</li>\n<li>regia Lorenzo Ponte</li>\n<li>scene e costumi Chiara Previato</li>\n<li>La voce dei Grandi \u00e8 di Alberto Mancioppi</li>\n<li>produzione Teatro Franco Parenti</li>\n<li>in collaborazione con Associazione Pier Lombardo</li>\n<li>Foto di Andea Salafia</li>\n</ul>\n<p>Milano. Anno 2123. Uma e Mo, adolescenti, vivono nella comunit\u00e0 nomade\ndei Grandi. Mo \u00e8 il maggiore, ma \u00e8 Uma a occuparsi di lui, a farsi carico per\nentrambi di tutte le responsabilit\u00e0. Mo \u00e8 malato e ha un segreto.\nVivono in una Milano colpita dalla siccit\u00e0, priva di ordine sociale, dove le\nrisorse elettriche sono limitate e ogni cosa, a causa della crisi climatica, si \u00e8\nfermata. Devono lavorare sottostando a regole infinite e punteggi impietosi.</p>\n<p>Il premio agognato \u00e8 un trasferimento sul Pianeta B, dove regna il benessere,\ndove l'acqua non \u00e8 razionata e puoi accendere la luce quando vuoi. Mentre Uma si impegna per il passaggio al pianeta B, Mo vaneggia sul Fuori, il\nterritorio proibito oltre i Distretti, dove la natura sopravvive nonostante i\ncambiamenti climatici. Possibile che il Pianeta B sia l'unica speranza? E se\nnel Fuori ci fosse una possibilit\u00e0 di recuperare il nostro rapporto con la\nnatura, con la nostra umanit\u00e0?</p>\n<p>Maggio / Novembre 2023</p>",
|
||||||
|
"html_content_en": "<ul>\n<li>directed by Lorenzo Ponte</li>\n<li>subject Giulia Lombezzi and Lorenzo Ponte</li>\n<li>dramaturgy Giulia Lombezzi</li>\n<li>with llaria Marchian\u00f2, Elia Galeotti</li>\n<li>scenes and costumes Chiara Previato</li>\n<li>Voice of the Greats Alberto Mancioppi</li>\n<li>production Teatro Franco Parenti in collaboration with the Pier Lombardo Association</li>\n<li>Photo by Andea Salafia</li>\n</ul>\n<p>Milan. Year 2123. Uma and Mo, teenagers, live in the nomadic community of\nthe Great Ones. Mo is the eldest, but it is Uma who takes care of him, who\ntakes on all the responsibilities for both of them. Mo is sick and has a secret.</p>\n<p>They live in a drought-stricken Milan, devoid of social order, where electricity\nresources are limited and everything, due to the climate crisis, has stopped.\nThey have to work under endless rules and merciless scores. The desired\nprize is a transfer to Planet B, where well-being reigns, where water is not\nrationed and you can turn on the light whenever you want. While Uma strives\nfor the transition to planet B, Mo raves about the Outside, the forbidden\nterritory beyond the Districts, where nature survives despite climate change.\nIs it possible that Planet B is the only hope? What if outside there was a\npossibility of recovering our relationship with nature, with our humanity?</p>\n<p>May / November 2023</p>"
|
||||||
|
},
|
||||||
|
"idomeneo": {
|
||||||
|
"name": [
|
||||||
|
"Idomeneo, re di Creta",
|
||||||
|
"Idomeneo, re di Creta"
|
||||||
|
],
|
||||||
|
"category": [
|
||||||
|
"Opera",
|
||||||
|
"Opera"
|
||||||
|
],
|
||||||
|
"main_picture": "Locandina.jpg",
|
||||||
|
"captions_it": {
|
||||||
|
"15 b.jpg": "",
|
||||||
|
"11 a.jpg": "",
|
||||||
|
"8.jpg": "",
|
||||||
|
"11 b.jpg": "",
|
||||||
|
"9 copia.jpg": "",
|
||||||
|
"16 b.jpg": "",
|
||||||
|
"15.jpg": "",
|
||||||
|
"17.jpg": "",
|
||||||
|
"16.jpg": "",
|
||||||
|
"10 copia.jpg": "",
|
||||||
|
"21.jpg": "",
|
||||||
|
"22.jpg": "",
|
||||||
|
"13 copia.jpg": "",
|
||||||
|
"18.jpg": "",
|
||||||
|
"19.jpg": "",
|
||||||
|
"4.jpg": "",
|
||||||
|
"14 copia.jpg": "",
|
||||||
|
"5.jpg": "",
|
||||||
|
"7.jpg": "",
|
||||||
|
"6.jpg": "",
|
||||||
|
"2.jpg": "",
|
||||||
|
"12 copia.jpg": "",
|
||||||
|
"3.jpg": "",
|
||||||
|
"1.jpg": ""
|
||||||
|
},
|
||||||
|
"captions_en": {
|
||||||
|
"15 b.jpg": "",
|
||||||
|
"11 a.jpg": "",
|
||||||
|
"8.jpg": "",
|
||||||
|
"11 b.jpg": "",
|
||||||
|
"9 copia.jpg": "",
|
||||||
|
"16 b.jpg": "",
|
||||||
|
"15.jpg": "",
|
||||||
|
"17.jpg": "",
|
||||||
|
"16.jpg": "",
|
||||||
|
"10 copia.jpg": "",
|
||||||
|
"21.jpg": "",
|
||||||
|
"22.jpg": "",
|
||||||
|
"13 copia.jpg": "",
|
||||||
|
"18.jpg": "",
|
||||||
|
"19.jpg": "",
|
||||||
|
"4.jpg": "",
|
||||||
|
"14 copia.jpg": "",
|
||||||
|
"5.jpg": "",
|
||||||
|
"7.jpg": "",
|
||||||
|
"6.jpg": "",
|
||||||
|
"2.jpg": "",
|
||||||
|
"12 copia.jpg": "",
|
||||||
|
"3.jpg": "",
|
||||||
|
"1.jpg": ""
|
||||||
|
},
|
||||||
|
"video_url": "<iframe src='https://www.youtube-nocookie.com/embed/-tvnTy_Bms8?si=OwxTfblTGI6QpA99' title='YouTube video player' frameborder='0' allow='accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share' referrerpolicy='strict-origin-when-cross-origin' allowfullscreen></iframe>",
|
||||||
|
"html_content_it": "<ul>\n<li>Musica Wolfgang Amadeus Mozart</li>\n<li>\n<p>Libretto Giambattista Varesco dal dramma di Danchet\n<br></p>\n</li>\n<li>\n<p>Nuova produzione Op\u00e9ra national de Lorraine</p>\n</li>\n<li>\n<p>OPERA NATIONAL DE LORRAINE ORCHESTRA E CORO\n<br></p>\n</li>\n<li>\n<p>Direttore Jakob Lehmann</p>\n</li>\n<li>\n<p>Regista Lorenzo Ponte\n<br></p>\n</li>\n<li>\n<p>Scene Alice Benazzi</p>\n</li>\n<li>Costumi Giulia Rossena</li>\n<li>Luci Emanuele Agliati</li>\n<li>Assistente alle luci Alessandro Manni</li>\n<li>\n<p>Foto di Simon Gosselin \n <br></p>\n</li>\n<li>\n<p>Direttore del coro Guillaume Fauch\u00e8re</p>\n</li>\n<li>Direttore assistente William Le Sage</li>\n</ul>\n<p><br></p>\n<ul>\n<li>Idomeneo Toby Spence</li>\n<li>damante Heloise Mas</li>\n<li>llia Siobhan Stagg</li>\n<li>Elettra Amanda Woodbury</li>\n<li>Arbace L\u00e9o Vermot-Desroches</li>\n<li>Il grande sacerdote* Wook Kang</li>\n<li>La voce di Nettuno Louis Morvan</li>\n<li>Donne Cretesi* Inna Jeskova e S\u00e9verine Maquaire</li>\n<li>Troiani* Yongwoo Jung e Jinhyuck Kim</li>\n<li>Coro lontano* Yongwoo Jung, IIl Ju Lee, Jinhyuck Kim e Christophe Sagnier</li>\n<li>Meda Rosabel Huguet</li>\n</ul>\n<p>*Solisti del Coro</p>\n<p>I miti si tramandano in versioni sempre diverse a seconda del luogo e del tempo.\nDopo la seconda guerra mondiale, Christa Wolf inizi\u00f2 a riscrivere i miti da una prospettiva\nche mise in discussione l'egemonia dei padri. Nel 2023 la storia di Idomeneo \u00e8 ancora\ntutta da interrogare: uomini e donne sono nelle mani degli dei, le scelte di un re venaono\nattribuite a un mostro, il sacrificio umano \u00e8 accettabile e l'amore \u00e8 raccontato come uno\nstrumento capace di guarire tutto.</p>\n<p>Partiamo dal conflitto con cui si conclude l'opera: il Dio del mare ha risolto tutto per tutti\ntranne che per un solo personaggio. Elettra grida che la gioia e l'amore le sono stati rubati.\nQual \u00e8 il crimine per il quale promette vendetta? Credo che ci sia qualcosa di pi\u00f9 profondo\ndel rifiuto di damante a muoverla a una tale rabbia. C'\u00e8 una violenza nascosta in questa\nfamiglia. Il sacrificio del bambino viene presentato come un incidente. Invece questo\nsacrificio, questa violenza sono le fondamenta stesse della civilt\u00e0 cretese.</p>\n<p>Nell'opera mancano totalmente i riferimenti alla Regina di Creta, moglie di Idomeneo e\nmadre di damante. E difficile persino rintracciare la sua presenza in altre fonti letterarie.\nSappiamo che si chiamava Meda e che fu uccisa per tradimento. Qual \u00e8 stato il tradimento che le \u00e8 costato una damnatio memoriae? Meda fu uccisa perch\u00e9 vide, perch\u00e9 sapeva su\nquale crimine giace Creta: l'abuso perpetuo del figlio da parte del Padre.</p>\n<p>Intorno a Idomeneo e alla sua famiglia c'\u00e8 una cultura che accetta e celebra il sacrificio,\nNel nostro allestimento siamo negli anni '60. Il Grande Sacerdote e il sacrificio saranno\nrappresentati come parti della liturgia cristiana, la religione del Padre. L'uccisione dei\nbambini \u00e8 gi\u00e0 avvenuta quando Idomeneo abusava di loro. La religione nasconde la verit\u00e0\ne tiene lontano l'orrore dagli uomini e dalle donne. L'abuso \u00e8 possibile perch\u00e9 c'\u00e8 una\ncomunit\u00e0 che lo tollera. Il coro interpreta le famiglie che abitano nei dintorni di Idomeneo.\nVogliono una vita pacifica, minacciata dal dolore di questi bambini, e quindi hanno bisogno\ndi un rito che guarisca e riporti la pace.</p>\n<p>\u00c8 Elettra a riaprire la ferita. Lei \u00e8 una donna di 30/35 anni degli anni 80 che viagger\u00e0 nella\nmemoria per trovare responsabilit\u00e0: vedr\u00e0 e ci mostrer\u00e0 nuovamente la Regina Meda e\nquindi una possibilit\u00e0 di un vero nuovo ordine basato non sulla violenza e sul sacrificio, ma\nsulla tutela dei deboli.</p>\n<p>Il set racconta questo viaggio nella memoria attraverso i mezzi della fotografia analogica. Il\nlavoro sulla memoria diventa il lavoro di sviluppo di un'immagine. I passaggi narrativi\nsaranno scanditi dal procedimento fotografico. Inizieremo da un album di famiglia da cui\nviene cancellato il corpo della madre e vedremo il volto della madre alla fine dell'opera.</p>\n<p>Christa Wolf ha scritto: \"A poco a poco, quando inizi a sapere, inizi anche a ricordare.\nConoscere e ricordare sono la stessa cosa\". Mentre la storia scritta da Varesco procede,\nla messa in scena mette le parole e le azioni dei personaggi sotto una luce diversa.\nQuesta storia \u00e8 raccontata dal punto di vista di una donna ritenuta pazza. Questa \u00e8 una\nstoria sul valore della testimonianza, sulla memoria e sulla responsabilita.</p>\n<p>Settembre - Ottobre 2023</p>",
|
||||||
|
"html_content_en": "<ul>\n<li>Libretto Father Giambattista Varesco after the play by Danchet</li>\n<li>\n<p>Music Wolfgang Amadeus Mozart\n <br></p>\n</li>\n<li>\n<p>New production Op\u00e9ra national de Lorraine</p>\n</li>\n<li>\n<p>OPERA NATIONAL DE LORRAINE ORCHESTRA AND CHORUS\n <br></p>\n</li>\n<li>\n<p>Conductor Jakob Lehmann</p>\n</li>\n<li>\n<p>Stage director Lorenzo Ponte\n <br></p>\n</li>\n<li>\n<p>Set design Alice Benazzi</p>\n</li>\n<li>Costumes Giulia Rossena</li>\n<li>Lighting Emanuele Agliati</li>\n<li>Lighting assistant Alessandro Manni</li>\n<li>\n<p>Pictures by Simon Gosselin\n <br></p>\n</li>\n<li>\n<p>Chorus master Guillaume Fauch\u00e8re</p>\n</li>\n<li>\n<p>Assistant conductor William Le Sage\n<br></p>\n</li>\n<li>\n<p>Idomeneo Toby Spence\ndamante H\u00e9lo\u00efse Mas</p>\n</li>\n<li>llia Siobhan Stagg</li>\n<li>Electre Amanda Woodbury</li>\n<li>Arbace L\u00e9o Vermot-Desroches</li>\n<li>The High Priest* Wook Kang</li>\n<li>The Voice of Neptune Louis Morvan</li>\n<li>Cretan women\u00ae Inna Jeskova and S\u00e9verine Maquaire</li>\n<li>Trojans<em> Yongwoo Jung and Jinhyuck Kim\nDistant chorus</em> Yongwoo Jung, Ill Ju Lee, Jinhyuck Kim and Christophe Sagnier</li>\n<li>Meda Rosabel Huguet</li>\n</ul>\n<p>*Opera Chorus soloists</p>\n<p>Muths have different versions. After World war II, Christa Wolf began to rewrite myths from\na perspective that questions the hegemony of the fathers. In 2023 the story of Idomeneo\nstill need to be questioned: men and women are in the hands of the gods, the choices of a\nking are blamed on a monster, human sacrifice is acceptable and love is told as a tool\ncapable to heal everything.</p>\n<p>We start from the conflict with which the opera ends: God apparently solves everything for\neveryone except for a single character. Electra cries out that joy and love have been stolen\nfrom her. What is the crime for which she pledges revenge? I believe there has to be\nsomething deeper than the love of Idamante. There is a hidden violence in this family. The\nsacrifice of the child is presented as an accident. Whereas this sacrifice, this violence are\nthe very foundations of the city.</p>\n<p>The opera is totally missing references to the Queen of Crete, wife of Idomeneo and\nmother of damante. It is even difficult to trace its presence in other literary sources. Her\nname was Meda and she was killed for treason. What was the betrayal that cost her a\ndamnatio memoriae? Meda was killed because she saw, because she knew on which\ncrime Crete lays: the perpetual abuse of the child by the Father. Around Idomeneo and his\nfamily there is a culture that accepts and celebrates the sacrifice. In our staging we are in\nthe 60's. The Great Priest and the sacrifice will be represented as parts of the Christian\nliturgy, the religion of the Father.</p>\n<p>The killing of the children has already taken place when Idomeneo abused of them.\nReligion hides the truth and keeps the horror away from men and women. The abuse is\npossible because there is a community who tolerates it. The chorus plays the families that\nlive nearby Idomeneo. They want a peaceful life, which is threatened by the pain of these\nchildren, and therefore they need a rite which heals and restore peace.\nElectra is the one who reopens the wound. She is a 30/35 years woman of the 80's who\nwill travel through memory to find responsibilities; she will see and show us again Queen\nMeda and therefore a possibility of a real new order based not on violence and sacrifice,\nbut on the protection of the weak.</p>\n<p>The set tell this trip into memory through the means of analogical photography. The work\non the memory becomes the work of developing a picture. The narrative passages will be\nmarked by the photographic process. We will start from a family album from which the\nbody of the mother is deleted and we will see the mother's face at the end of the opera.</p>\n<p>Christa Wolf wrote: \"Little by little, when you begin to know, you begin to remember too.\nKnowing and remembering are the same thing\". While the story of Varesco goes along, the\nstaging puts the words and the actions of the characters under a different light. This story\nis told from the perspective of a woman who is thought to be insane. This is a story about\nthe value of testimony, about memory and responsibility.</p>\n<p>September - October 2023</p>"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"categories": [
|
||||||
|
[
|
||||||
|
"Opera",
|
||||||
|
"Opera"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"Prosa",
|
||||||
|
"Theater"
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
@ -0,0 +1 @@
|
|||||||
|
pip
|
@ -0,0 +1,28 @@
|
|||||||
|
Copyright 2007 Pallets
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are
|
||||||
|
met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
3. Neither the name of the copyright holder nor the names of its
|
||||||
|
contributors may be used to endorse or promote products derived from
|
||||||
|
this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||||
|
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
@ -0,0 +1,105 @@
|
|||||||
|
Metadata-Version: 2.1
|
||||||
|
Name: Jinja2
|
||||||
|
Version: 3.1.3
|
||||||
|
Summary: A very fast and expressive template engine.
|
||||||
|
Home-page: https://palletsprojects.com/p/jinja/
|
||||||
|
Maintainer: Pallets
|
||||||
|
Maintainer-email: contact@palletsprojects.com
|
||||||
|
License: BSD-3-Clause
|
||||||
|
Project-URL: Donate, https://palletsprojects.com/donate
|
||||||
|
Project-URL: Documentation, https://jinja.palletsprojects.com/
|
||||||
|
Project-URL: Changes, https://jinja.palletsprojects.com/changes/
|
||||||
|
Project-URL: Source Code, https://github.com/pallets/jinja/
|
||||||
|
Project-URL: Issue Tracker, https://github.com/pallets/jinja/issues/
|
||||||
|
Project-URL: Chat, https://discord.gg/pallets
|
||||||
|
Classifier: Development Status :: 5 - Production/Stable
|
||||||
|
Classifier: Environment :: Web Environment
|
||||||
|
Classifier: Intended Audience :: Developers
|
||||||
|
Classifier: License :: OSI Approved :: BSD License
|
||||||
|
Classifier: Operating System :: OS Independent
|
||||||
|
Classifier: Programming Language :: Python
|
||||||
|
Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
|
||||||
|
Classifier: Topic :: Text Processing :: Markup :: HTML
|
||||||
|
Requires-Python: >=3.7
|
||||||
|
Description-Content-Type: text/x-rst
|
||||||
|
License-File: LICENSE.rst
|
||||||
|
Requires-Dist: MarkupSafe >=2.0
|
||||||
|
Provides-Extra: i18n
|
||||||
|
Requires-Dist: Babel >=2.7 ; extra == 'i18n'
|
||||||
|
|
||||||
|
Jinja
|
||||||
|
=====
|
||||||
|
|
||||||
|
Jinja is a fast, expressive, extensible templating engine. Special
|
||||||
|
placeholders in the template allow writing code similar to Python
|
||||||
|
syntax. Then the template is passed data to render the final document.
|
||||||
|
|
||||||
|
It includes:
|
||||||
|
|
||||||
|
- Template inheritance and inclusion.
|
||||||
|
- Define and import macros within templates.
|
||||||
|
- HTML templates can use autoescaping to prevent XSS from untrusted
|
||||||
|
user input.
|
||||||
|
- A sandboxed environment can safely render untrusted templates.
|
||||||
|
- AsyncIO support for generating templates and calling async
|
||||||
|
functions.
|
||||||
|
- I18N support with Babel.
|
||||||
|
- Templates are compiled to optimized Python code just-in-time and
|
||||||
|
cached, or can be compiled ahead-of-time.
|
||||||
|
- Exceptions point to the correct line in templates to make debugging
|
||||||
|
easier.
|
||||||
|
- Extensible filters, tests, functions, and even syntax.
|
||||||
|
|
||||||
|
Jinja's philosophy is that while application logic belongs in Python if
|
||||||
|
possible, it shouldn't make the template designer's job difficult by
|
||||||
|
restricting functionality too much.
|
||||||
|
|
||||||
|
|
||||||
|
Installing
|
||||||
|
----------
|
||||||
|
|
||||||
|
Install and update using `pip`_:
|
||||||
|
|
||||||
|
.. code-block:: text
|
||||||
|
|
||||||
|
$ pip install -U Jinja2
|
||||||
|
|
||||||
|
.. _pip: https://pip.pypa.io/en/stable/getting-started/
|
||||||
|
|
||||||
|
|
||||||
|
In A Nutshell
|
||||||
|
-------------
|
||||||
|
|
||||||
|
.. code-block:: jinja
|
||||||
|
|
||||||
|
{% extends "base.html" %}
|
||||||
|
{% block title %}Members{% endblock %}
|
||||||
|
{% block content %}
|
||||||
|
<ul>
|
||||||
|
{% for user in users %}
|
||||||
|
<li><a href="{{ user.url }}">{{ user.username }}</a></li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
|
||||||
|
Donate
|
||||||
|
------
|
||||||
|
|
||||||
|
The Pallets organization develops and supports Jinja and other popular
|
||||||
|
packages. In order to grow the community of contributors and users, and
|
||||||
|
allow the maintainers to devote more time to the projects, `please
|
||||||
|
donate today`_.
|
||||||
|
|
||||||
|
.. _please donate today: https://palletsprojects.com/donate
|
||||||
|
|
||||||
|
|
||||||
|
Links
|
||||||
|
-----
|
||||||
|
|
||||||
|
- Documentation: https://jinja.palletsprojects.com/
|
||||||
|
- Changes: https://jinja.palletsprojects.com/changes/
|
||||||
|
- PyPI Releases: https://pypi.org/project/Jinja2/
|
||||||
|
- Source Code: https://github.com/pallets/jinja/
|
||||||
|
- Issue Tracker: https://github.com/pallets/jinja/issues/
|
||||||
|
- Chat: https://discord.gg/pallets
|
@ -0,0 +1,59 @@
|
|||||||
|
Jinja2-3.1.3.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
|
||||||
|
Jinja2-3.1.3.dist-info/LICENSE.rst,sha256=O0nc7kEF6ze6wQ-vG-JgQI_oXSUrjp3y4JefweCUQ3s,1475
|
||||||
|
Jinja2-3.1.3.dist-info/METADATA,sha256=0cLNbRCI91jytc7Bzv3XAQfZzFDF2gxkJuH46eF5vew,3301
|
||||||
|
Jinja2-3.1.3.dist-info/RECORD,,
|
||||||
|
Jinja2-3.1.3.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
||||||
|
Jinja2-3.1.3.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
|
||||||
|
Jinja2-3.1.3.dist-info/entry_points.txt,sha256=zRd62fbqIyfUpsRtU7EVIFyiu1tPwfgO7EvPErnxgTE,59
|
||||||
|
Jinja2-3.1.3.dist-info/top_level.txt,sha256=PkeVWtLb3-CqjWi1fO29OCbj55EhX_chhKrCdrVe_zs,7
|
||||||
|
jinja2/__init__.py,sha256=NTBwMwsECrdHmxeXF7seusHLzrh6Ldn1A9qhS5cDuf0,1927
|
||||||
|
jinja2/__pycache__/__init__.cpython-312.pyc,,
|
||||||
|
jinja2/__pycache__/_identifier.cpython-312.pyc,,
|
||||||
|
jinja2/__pycache__/async_utils.cpython-312.pyc,,
|
||||||
|
jinja2/__pycache__/bccache.cpython-312.pyc,,
|
||||||
|
jinja2/__pycache__/compiler.cpython-312.pyc,,
|
||||||
|
jinja2/__pycache__/constants.cpython-312.pyc,,
|
||||||
|
jinja2/__pycache__/debug.cpython-312.pyc,,
|
||||||
|
jinja2/__pycache__/defaults.cpython-312.pyc,,
|
||||||
|
jinja2/__pycache__/environment.cpython-312.pyc,,
|
||||||
|
jinja2/__pycache__/exceptions.cpython-312.pyc,,
|
||||||
|
jinja2/__pycache__/ext.cpython-312.pyc,,
|
||||||
|
jinja2/__pycache__/filters.cpython-312.pyc,,
|
||||||
|
jinja2/__pycache__/idtracking.cpython-312.pyc,,
|
||||||
|
jinja2/__pycache__/lexer.cpython-312.pyc,,
|
||||||
|
jinja2/__pycache__/loaders.cpython-312.pyc,,
|
||||||
|
jinja2/__pycache__/meta.cpython-312.pyc,,
|
||||||
|
jinja2/__pycache__/nativetypes.cpython-312.pyc,,
|
||||||
|
jinja2/__pycache__/nodes.cpython-312.pyc,,
|
||||||
|
jinja2/__pycache__/optimizer.cpython-312.pyc,,
|
||||||
|
jinja2/__pycache__/parser.cpython-312.pyc,,
|
||||||
|
jinja2/__pycache__/runtime.cpython-312.pyc,,
|
||||||
|
jinja2/__pycache__/sandbox.cpython-312.pyc,,
|
||||||
|
jinja2/__pycache__/tests.cpython-312.pyc,,
|
||||||
|
jinja2/__pycache__/utils.cpython-312.pyc,,
|
||||||
|
jinja2/__pycache__/visitor.cpython-312.pyc,,
|
||||||
|
jinja2/_identifier.py,sha256=_zYctNKzRqlk_murTNlzrju1FFJL7Va_Ijqqd7ii2lU,1958
|
||||||
|
jinja2/async_utils.py,sha256=dFcmh6lMNfbh7eLKrBio8JqAKLHdZbpCuurFN4OERtY,2447
|
||||||
|
jinja2/bccache.py,sha256=mhz5xtLxCcHRAa56azOhphIAe19u1we0ojifNMClDio,14061
|
||||||
|
jinja2/compiler.py,sha256=PJzYdRLStlEOqmnQs1YxlizPrJoj3jTZuUleREn6AIQ,72199
|
||||||
|
jinja2/constants.py,sha256=GMoFydBF_kdpaRKPoM5cl5MviquVRLVyZtfp5-16jg0,1433
|
||||||
|
jinja2/debug.py,sha256=iWJ432RadxJNnaMOPrjIDInz50UEgni3_HKuFXi2vuQ,6299
|
||||||
|
jinja2/defaults.py,sha256=boBcSw78h-lp20YbaXSJsqkAI2uN_mD_TtCydpeq5wU,1267
|
||||||
|
jinja2/environment.py,sha256=0qldX3VQKZcm6lgn7zHz94oRFow7YPYERiqkquomNjU,61253
|
||||||
|
jinja2/exceptions.py,sha256=ioHeHrWwCWNaXX1inHmHVblvc4haO7AXsjCp3GfWvx0,5071
|
||||||
|
jinja2/ext.py,sha256=5fnMpllaXkfm2P_93RIvi-OnK7Tk8mCW8Du-GcD12Hc,31844
|
||||||
|
jinja2/filters.py,sha256=vYjKb2zaPShvYtn_LpSmqfS8SScbrA_KOanNibsMDIE,53862
|
||||||
|
jinja2/idtracking.py,sha256=GfNmadir4oDALVxzn3DL9YInhJDr69ebXeA2ygfuCGA,10704
|
||||||
|
jinja2/lexer.py,sha256=DW2nX9zk-6MWp65YR2bqqj0xqCvLtD-u9NWT8AnFRxQ,29726
|
||||||
|
jinja2/loaders.py,sha256=ayAwxfrA1SAffQta0nwSDm3TDT4KYiIGN_D9Z45B310,23085
|
||||||
|
jinja2/meta.py,sha256=GNPEvifmSaU3CMxlbheBOZjeZ277HThOPUTf1RkppKQ,4396
|
||||||
|
jinja2/nativetypes.py,sha256=7GIGALVJgdyL80oZJdQUaUfwSt5q2lSSZbXt0dNf_M4,4210
|
||||||
|
jinja2/nodes.py,sha256=i34GPRAZexXMT6bwuf5SEyvdmS-bRCy9KMjwN5O6pjk,34550
|
||||||
|
jinja2/optimizer.py,sha256=tHkMwXxfZkbfA1KmLcqmBMSaz7RLIvvItrJcPoXTyD8,1650
|
||||||
|
jinja2/parser.py,sha256=Y199wPL-G67gJoi5G_5sHuu9uEP1PJkjjLEW_xTH8-k,39736
|
||||||
|
jinja2/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
||||||
|
jinja2/runtime.py,sha256=_6LkKIWFJjQdqlrgA3K39zBFQ-7Orm3wGDm96RwxQoE,33406
|
||||||
|
jinja2/sandbox.py,sha256=Y0xZeXQnH6EX5VjaV2YixESxoepnRbW_3UeQosaBU3M,14584
|
||||||
|
jinja2/tests.py,sha256=Am5Z6Lmfr2XaH_npIfJJ8MdXtWsbLjMULZJulTAj30E,5905
|
||||||
|
jinja2/utils.py,sha256=IMwRIcN1SsTw2-jdQtlH2KzNABsXZBW_-tnFXafQBvY,23933
|
||||||
|
jinja2/visitor.py,sha256=MH14C6yq24G_KVtWzjwaI7Wg14PCJIYlWW1kpkxYak0,3568
|
@ -0,0 +1,5 @@
|
|||||||
|
Wheel-Version: 1.0
|
||||||
|
Generator: bdist_wheel (0.42.0)
|
||||||
|
Root-Is-Purelib: true
|
||||||
|
Tag: py3-none-any
|
||||||
|
|
@ -0,0 +1,2 @@
|
|||||||
|
[babel.extractors]
|
||||||
|
jinja2 = jinja2.ext:babel_extract[i18n]
|
@ -0,0 +1 @@
|
|||||||
|
jinja2
|
@ -0,0 +1 @@
|
|||||||
|
pip
|
@ -0,0 +1,30 @@
|
|||||||
|
BSD 3-Clause License
|
||||||
|
|
||||||
|
Copyright 2007, 2008 The Python Markdown Project (v. 1.7 and later)
|
||||||
|
Copyright 2004, 2005, 2006 Yuri Takhteyev (v. 0.2-1.6b)
|
||||||
|
Copyright 2004 Manfred Stienstra (the original version)
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer.
|
||||||
|
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer in the documentation
|
||||||
|
and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
3. Neither the name of the copyright holder nor the names of its
|
||||||
|
contributors may be used to endorse or promote products derived from
|
||||||
|
this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
|
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
|
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
|
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
@ -0,0 +1,146 @@
|
|||||||
|
Metadata-Version: 2.1
|
||||||
|
Name: Markdown
|
||||||
|
Version: 3.6
|
||||||
|
Summary: Python implementation of John Gruber's Markdown.
|
||||||
|
Author: Manfred Stienstra, Yuri Takhteyev
|
||||||
|
Author-email: Waylan limberg <python.markdown@gmail.com>
|
||||||
|
Maintainer: Isaac Muse
|
||||||
|
Maintainer-email: Waylan Limberg <python.markdown@gmail.com>
|
||||||
|
License: BSD 3-Clause License
|
||||||
|
|
||||||
|
Copyright 2007, 2008 The Python Markdown Project (v. 1.7 and later)
|
||||||
|
Copyright 2004, 2005, 2006 Yuri Takhteyev (v. 0.2-1.6b)
|
||||||
|
Copyright 2004 Manfred Stienstra (the original version)
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer.
|
||||||
|
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer in the documentation
|
||||||
|
and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
3. Neither the name of the copyright holder nor the names of its
|
||||||
|
contributors may be used to endorse or promote products derived from
|
||||||
|
this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
|
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
|
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
|
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
Project-URL: Homepage, https://Python-Markdown.github.io/
|
||||||
|
Project-URL: Documentation, https://Python-Markdown.github.io/
|
||||||
|
Project-URL: Repository, https://github.com/Python-Markdown/markdown
|
||||||
|
Project-URL: Issue Tracker, https://github.com/Python-Markdown/markdown/issues
|
||||||
|
Project-URL: Changelog, https://python-markdown.github.io/changelog/
|
||||||
|
Keywords: markdown,markdown-parser,python-markdown,markdown-to-html
|
||||||
|
Classifier: Development Status :: 5 - Production/Stable
|
||||||
|
Classifier: License :: OSI Approved :: BSD License
|
||||||
|
Classifier: Operating System :: OS Independent
|
||||||
|
Classifier: Programming Language :: Python
|
||||||
|
Classifier: Programming Language :: Python :: 3
|
||||||
|
Classifier: Programming Language :: Python :: 3.8
|
||||||
|
Classifier: Programming Language :: Python :: 3.9
|
||||||
|
Classifier: Programming Language :: Python :: 3.10
|
||||||
|
Classifier: Programming Language :: Python :: 3.11
|
||||||
|
Classifier: Programming Language :: Python :: 3.12
|
||||||
|
Classifier: Programming Language :: Python :: 3 :: Only
|
||||||
|
Classifier: Programming Language :: Python :: Implementation :: CPython
|
||||||
|
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
||||||
|
Classifier: Topic :: Communications :: Email :: Filters
|
||||||
|
Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content :: CGI Tools/Libraries
|
||||||
|
Classifier: Topic :: Internet :: WWW/HTTP :: Site Management
|
||||||
|
Classifier: Topic :: Software Development :: Documentation
|
||||||
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
||||||
|
Classifier: Topic :: Text Processing :: Filters
|
||||||
|
Classifier: Topic :: Text Processing :: Markup :: HTML
|
||||||
|
Classifier: Topic :: Text Processing :: Markup :: Markdown
|
||||||
|
Requires-Python: >=3.8
|
||||||
|
Description-Content-Type: text/markdown
|
||||||
|
License-File: LICENSE.md
|
||||||
|
Requires-Dist: importlib-metadata >=4.4 ; python_version < "3.10"
|
||||||
|
Provides-Extra: docs
|
||||||
|
Requires-Dist: mkdocs >=1.5 ; extra == 'docs'
|
||||||
|
Requires-Dist: mkdocs-nature >=0.6 ; extra == 'docs'
|
||||||
|
Requires-Dist: mdx-gh-links >=0.2 ; extra == 'docs'
|
||||||
|
Requires-Dist: mkdocstrings[python] ; extra == 'docs'
|
||||||
|
Requires-Dist: mkdocs-gen-files ; extra == 'docs'
|
||||||
|
Requires-Dist: mkdocs-section-index ; extra == 'docs'
|
||||||
|
Requires-Dist: mkdocs-literate-nav ; extra == 'docs'
|
||||||
|
Provides-Extra: testing
|
||||||
|
Requires-Dist: coverage ; extra == 'testing'
|
||||||
|
Requires-Dist: pyyaml ; extra == 'testing'
|
||||||
|
|
||||||
|
[Python-Markdown][]
|
||||||
|
===================
|
||||||
|
|
||||||
|
[![Build Status][build-button]][build]
|
||||||
|
[![Coverage Status][codecov-button]][codecov]
|
||||||
|
[![Latest Version][mdversion-button]][md-pypi]
|
||||||
|
[![Python Versions][pyversion-button]][md-pypi]
|
||||||
|
[![BSD License][bsdlicense-button]][bsdlicense]
|
||||||
|
[![Code of Conduct][codeofconduct-button]][Code of Conduct]
|
||||||
|
|
||||||
|
[build-button]: https://github.com/Python-Markdown/markdown/workflows/CI/badge.svg?event=push
|
||||||
|
[build]: https://github.com/Python-Markdown/markdown/actions?query=workflow%3ACI+event%3Apush
|
||||||
|
[codecov-button]: https://codecov.io/gh/Python-Markdown/markdown/branch/master/graph/badge.svg
|
||||||
|
[codecov]: https://codecov.io/gh/Python-Markdown/markdown
|
||||||
|
[mdversion-button]: https://img.shields.io/pypi/v/Markdown.svg
|
||||||
|
[md-pypi]: https://pypi.org/project/Markdown/
|
||||||
|
[pyversion-button]: https://img.shields.io/pypi/pyversions/Markdown.svg
|
||||||
|
[bsdlicense-button]: https://img.shields.io/badge/license-BSD-yellow.svg
|
||||||
|
[bsdlicense]: https://opensource.org/licenses/BSD-3-Clause
|
||||||
|
[codeofconduct-button]: https://img.shields.io/badge/code%20of%20conduct-contributor%20covenant-green.svg?style=flat-square
|
||||||
|
[Code of Conduct]: https://github.com/Python-Markdown/markdown/blob/master/CODE_OF_CONDUCT.md
|
||||||
|
|
||||||
|
This is a Python implementation of John Gruber's [Markdown][].
|
||||||
|
It is almost completely compliant with the reference implementation,
|
||||||
|
though there are a few known issues. See [Features][] for information
|
||||||
|
on what exactly is supported and what is not. Additional features are
|
||||||
|
supported by the [Available Extensions][].
|
||||||
|
|
||||||
|
[Python-Markdown]: https://Python-Markdown.github.io/
|
||||||
|
[Markdown]: https://daringfireball.net/projects/markdown/
|
||||||
|
[Features]: https://Python-Markdown.github.io#Features
|
||||||
|
[Available Extensions]: https://Python-Markdown.github.io/extensions
|
||||||
|
|
||||||
|
Documentation
|
||||||
|
-------------
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pip install markdown
|
||||||
|
```
|
||||||
|
```python
|
||||||
|
import markdown
|
||||||
|
html = markdown.markdown(your_text_string)
|
||||||
|
```
|
||||||
|
|
||||||
|
For more advanced [installation] and [usage] documentation, see the `docs/` directory
|
||||||
|
of the distribution or the project website at <https://Python-Markdown.github.io/>.
|
||||||
|
|
||||||
|
[installation]: https://python-markdown.github.io/install/
|
||||||
|
[usage]: https://python-markdown.github.io/reference/
|
||||||
|
|
||||||
|
See the change log at <https://python-markdown.github.io/changelog/>.
|
||||||
|
|
||||||
|
Support
|
||||||
|
-------
|
||||||
|
|
||||||
|
You may report bugs, ask for help, and discuss various other issues on the [bug tracker][].
|
||||||
|
|
||||||
|
[bug tracker]: https://github.com/Python-Markdown/markdown/issues
|
||||||
|
|
||||||
|
Code of Conduct
|
||||||
|
---------------
|
||||||
|
|
||||||
|
Everyone interacting in the Python-Markdown project's code bases, issue trackers,
|
||||||
|
and mailing lists is expected to follow the [Code of Conduct].
|
@ -0,0 +1,75 @@
|
|||||||
|
../../../bin/markdown_py,sha256=4ZgxDp0aOu2bvhxlP5wPJakDcatfwd6VqZhBNEDSA6U,243
|
||||||
|
Markdown-3.6.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
|
||||||
|
Markdown-3.6.dist-info/LICENSE.md,sha256=e6TrbRCzKy0R3OE4ITQDUc27swuozMZ4Qdsv_Ybnmso,1650
|
||||||
|
Markdown-3.6.dist-info/METADATA,sha256=8_ETqzTxcOemQXj7ujUabMFcDBDGtsRrccFDr1-XWvc,7040
|
||||||
|
Markdown-3.6.dist-info/RECORD,,
|
||||||
|
Markdown-3.6.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
||||||
|
Markdown-3.6.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
|
||||||
|
Markdown-3.6.dist-info/entry_points.txt,sha256=lMEyiiA_ZZyfPCBlDviBl-SiU0cfoeuEKpwxw361sKQ,1102
|
||||||
|
Markdown-3.6.dist-info/top_level.txt,sha256=IAxs8x618RXoH1uCqeLLxXsDefJvE_mIibr_M4sOlyk,9
|
||||||
|
markdown/__init__.py,sha256=dfzwwdpG9L8QLEPBpLFPIHx_BN056aZXp9xZifTxYIU,1777
|
||||||
|
markdown/__main__.py,sha256=innFBxRqwPBNxG1zhKktJji4bnRKtVyYYd30ID13Tcw,5859
|
||||||
|
markdown/__meta__.py,sha256=DqtqnYYLznrkvI1G4JalBc4WpgOp48naNoG9zlMWZas,1712
|
||||||
|
markdown/__pycache__/__init__.cpython-312.pyc,,
|
||||||
|
markdown/__pycache__/__main__.cpython-312.pyc,,
|
||||||
|
markdown/__pycache__/__meta__.cpython-312.pyc,,
|
||||||
|
markdown/__pycache__/blockparser.cpython-312.pyc,,
|
||||||
|
markdown/__pycache__/blockprocessors.cpython-312.pyc,,
|
||||||
|
markdown/__pycache__/core.cpython-312.pyc,,
|
||||||
|
markdown/__pycache__/htmlparser.cpython-312.pyc,,
|
||||||
|
markdown/__pycache__/inlinepatterns.cpython-312.pyc,,
|
||||||
|
markdown/__pycache__/postprocessors.cpython-312.pyc,,
|
||||||
|
markdown/__pycache__/preprocessors.cpython-312.pyc,,
|
||||||
|
markdown/__pycache__/serializers.cpython-312.pyc,,
|
||||||
|
markdown/__pycache__/test_tools.cpython-312.pyc,,
|
||||||
|
markdown/__pycache__/treeprocessors.cpython-312.pyc,,
|
||||||
|
markdown/__pycache__/util.cpython-312.pyc,,
|
||||||
|
markdown/blockparser.py,sha256=j4CQImVpiq7g9pz8wCxvzT61X_T2iSAjXupHJk8P3eA,5728
|
||||||
|
markdown/blockprocessors.py,sha256=koY5rq8DixzBCHcquvZJp6x2JYyBGjrwxMWNZhd6D2U,27013
|
||||||
|
markdown/core.py,sha256=DyyzDsmd-KcuEp8ZWUKJAeUCt7B7G3J3NeqZqp3LphI,21335
|
||||||
|
markdown/extensions/__init__.py,sha256=9z1khsdKCVrmrJ_2GfxtPAdjD3FyMe5vhC7wmM4O9m0,4822
|
||||||
|
markdown/extensions/__pycache__/__init__.cpython-312.pyc,,
|
||||||
|
markdown/extensions/__pycache__/abbr.cpython-312.pyc,,
|
||||||
|
markdown/extensions/__pycache__/admonition.cpython-312.pyc,,
|
||||||
|
markdown/extensions/__pycache__/attr_list.cpython-312.pyc,,
|
||||||
|
markdown/extensions/__pycache__/codehilite.cpython-312.pyc,,
|
||||||
|
markdown/extensions/__pycache__/def_list.cpython-312.pyc,,
|
||||||
|
markdown/extensions/__pycache__/extra.cpython-312.pyc,,
|
||||||
|
markdown/extensions/__pycache__/fenced_code.cpython-312.pyc,,
|
||||||
|
markdown/extensions/__pycache__/footnotes.cpython-312.pyc,,
|
||||||
|
markdown/extensions/__pycache__/legacy_attrs.cpython-312.pyc,,
|
||||||
|
markdown/extensions/__pycache__/legacy_em.cpython-312.pyc,,
|
||||||
|
markdown/extensions/__pycache__/md_in_html.cpython-312.pyc,,
|
||||||
|
markdown/extensions/__pycache__/meta.cpython-312.pyc,,
|
||||||
|
markdown/extensions/__pycache__/nl2br.cpython-312.pyc,,
|
||||||
|
markdown/extensions/__pycache__/sane_lists.cpython-312.pyc,,
|
||||||
|
markdown/extensions/__pycache__/smarty.cpython-312.pyc,,
|
||||||
|
markdown/extensions/__pycache__/tables.cpython-312.pyc,,
|
||||||
|
markdown/extensions/__pycache__/toc.cpython-312.pyc,,
|
||||||
|
markdown/extensions/__pycache__/wikilinks.cpython-312.pyc,,
|
||||||
|
markdown/extensions/abbr.py,sha256=JqFOfU7JlhIFY06-nZnSU0wDqneFKKWMe95eXB-iLtc,3250
|
||||||
|
markdown/extensions/admonition.py,sha256=Hqcn3I8JG0i-OPWdoqI189TmlQRgH6bs5PmpCANyLlg,6547
|
||||||
|
markdown/extensions/attr_list.py,sha256=t3PrgAr5Ebldnq3nJNbteBt79bN0ccXS5RemmQfUZ9g,7820
|
||||||
|
markdown/extensions/codehilite.py,sha256=ChlmpM6S--j-UK7t82859UpYjm8EftdiLqmgDnknyes,13503
|
||||||
|
markdown/extensions/def_list.py,sha256=J3NVa6CllfZPsboJCEycPyRhtjBHnOn8ET6omEvVlDo,4029
|
||||||
|
markdown/extensions/extra.py,sha256=1vleT284kued4HQBtF83IjSumJVo0q3ng6MjTkVNfNQ,2163
|
||||||
|
markdown/extensions/fenced_code.py,sha256=-fYSmRZ9DTYQ8HO9b_78i47kVyVu6mcVJlqVTMdzvo4,8300
|
||||||
|
markdown/extensions/footnotes.py,sha256=bRFlmIBOKDI5efG1jZfDkMoV2osfqWip1rN1j2P-mMg,16710
|
||||||
|
markdown/extensions/legacy_attrs.py,sha256=oWcyNrfP0F6zsBoBOaD5NiwrJyy4kCpgQLl12HA7JGU,2788
|
||||||
|
markdown/extensions/legacy_em.py,sha256=-Z_w4PEGSS-Xg-2-BtGAnXwwy5g5GDgv2tngASnPgxg,1693
|
||||||
|
markdown/extensions/md_in_html.py,sha256=y4HEWEnkvfih22fojcaJeAmjx1AtF8N-a_jb6IDFfts,16546
|
||||||
|
markdown/extensions/meta.py,sha256=v_4Uq7nbcQ76V1YAvqVPiNLbRLIQHJsnfsk-tN70RmY,2600
|
||||||
|
markdown/extensions/nl2br.py,sha256=9KKcrPs62c3ENNnmOJZs0rrXXqUtTCfd43j1_OPpmgU,1090
|
||||||
|
markdown/extensions/sane_lists.py,sha256=ogAKcm7gEpcXV7fSTf8JZH5YdKAssPCEOUzdGM3C9Tw,2150
|
||||||
|
markdown/extensions/smarty.py,sha256=yqT0OiE2AqYrqqZtcUFFmp2eJsQHomiKzgyG2JFb9rI,11048
|
||||||
|
markdown/extensions/tables.py,sha256=oTDvGD1qp9xjVWPGYNgDBWe9NqsX5gS6UU5wUsQ1bC8,8741
|
||||||
|
markdown/extensions/toc.py,sha256=PGg-EqbBubm3n0b633r8Xa9kc6JIdbo20HGAOZ6GEl8,18322
|
||||||
|
markdown/extensions/wikilinks.py,sha256=j7D2sozica6sqXOUa_GuAXqIzxp-7Hi60bfXymiuma8,3285
|
||||||
|
markdown/htmlparser.py,sha256=dEr6IE7i9b6Tc1gdCLZGeWw6g6-E-jK1Z4KPj8yGk8Q,14332
|
||||||
|
markdown/inlinepatterns.py,sha256=7_HF5nTOyQag_CyBgU4wwmuI6aMjtadvGadyS9IP21w,38256
|
||||||
|
markdown/postprocessors.py,sha256=eYi6eW0mGudmWpmsW45hduLwX66Zr8Bf44WyU9vKp-I,4807
|
||||||
|
markdown/preprocessors.py,sha256=pq5NnHKkOSVQeIo-ajC-Yt44kvyMV97D04FBOQXctJM,3224
|
||||||
|
markdown/serializers.py,sha256=YtAFYQoOdp_TAmYGow6nBo0eB6I-Sl4PTLdLDfQJHwQ,7174
|
||||||
|
markdown/test_tools.py,sha256=MtN4cf3ZPDtb83wXLTol-3q3aIGRIkJ2zWr6fd-RgVE,8662
|
||||||
|
markdown/treeprocessors.py,sha256=o4dnoZZsIeVV8qR45Njr8XgwKleWYDS5pv8dKQhJvv8,17651
|
||||||
|
markdown/util.py,sha256=vJ1E0xjMzDAlTqLUSJWgdEvxdQfLXDEYUssOQMw9kPQ,13929
|
@ -0,0 +1,5 @@
|
|||||||
|
Wheel-Version: 1.0
|
||||||
|
Generator: bdist_wheel (0.43.0)
|
||||||
|
Root-Is-Purelib: true
|
||||||
|
Tag: py3-none-any
|
||||||
|
|
@ -0,0 +1,22 @@
|
|||||||
|
[console_scripts]
|
||||||
|
markdown_py = markdown.__main__:run
|
||||||
|
|
||||||
|
[markdown.extensions]
|
||||||
|
abbr = markdown.extensions.abbr:AbbrExtension
|
||||||
|
admonition = markdown.extensions.admonition:AdmonitionExtension
|
||||||
|
attr_list = markdown.extensions.attr_list:AttrListExtension
|
||||||
|
codehilite = markdown.extensions.codehilite:CodeHiliteExtension
|
||||||
|
def_list = markdown.extensions.def_list:DefListExtension
|
||||||
|
extra = markdown.extensions.extra:ExtraExtension
|
||||||
|
fenced_code = markdown.extensions.fenced_code:FencedCodeExtension
|
||||||
|
footnotes = markdown.extensions.footnotes:FootnoteExtension
|
||||||
|
legacy_attrs = markdown.extensions.legacy_attrs:LegacyAttrExtension
|
||||||
|
legacy_em = markdown.extensions.legacy_em:LegacyEmExtension
|
||||||
|
md_in_html = markdown.extensions.md_in_html:MarkdownInHtmlExtension
|
||||||
|
meta = markdown.extensions.meta:MetaExtension
|
||||||
|
nl2br = markdown.extensions.nl2br:Nl2BrExtension
|
||||||
|
sane_lists = markdown.extensions.sane_lists:SaneListExtension
|
||||||
|
smarty = markdown.extensions.smarty:SmartyExtension
|
||||||
|
tables = markdown.extensions.tables:TableExtension
|
||||||
|
toc = markdown.extensions.toc:TocExtension
|
||||||
|
wikilinks = markdown.extensions.wikilinks:WikiLinkExtension
|
@ -0,0 +1 @@
|
|||||||
|
markdown
|
@ -0,0 +1 @@
|
|||||||
|
pip
|
@ -0,0 +1,28 @@
|
|||||||
|
Copyright 2010 Pallets
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are
|
||||||
|
met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
3. Neither the name of the copyright holder nor the names of its
|
||||||
|
contributors may be used to endorse or promote products derived from
|
||||||
|
this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||||
|
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
@ -0,0 +1,93 @@
|
|||||||
|
Metadata-Version: 2.1
|
||||||
|
Name: MarkupSafe
|
||||||
|
Version: 2.1.5
|
||||||
|
Summary: Safely add untrusted strings to HTML/XML markup.
|
||||||
|
Home-page: https://palletsprojects.com/p/markupsafe/
|
||||||
|
Maintainer: Pallets
|
||||||
|
Maintainer-email: contact@palletsprojects.com
|
||||||
|
License: BSD-3-Clause
|
||||||
|
Project-URL: Donate, https://palletsprojects.com/donate
|
||||||
|
Project-URL: Documentation, https://markupsafe.palletsprojects.com/
|
||||||
|
Project-URL: Changes, https://markupsafe.palletsprojects.com/changes/
|
||||||
|
Project-URL: Source Code, https://github.com/pallets/markupsafe/
|
||||||
|
Project-URL: Issue Tracker, https://github.com/pallets/markupsafe/issues/
|
||||||
|
Project-URL: Chat, https://discord.gg/pallets
|
||||||
|
Classifier: Development Status :: 5 - Production/Stable
|
||||||
|
Classifier: Environment :: Web Environment
|
||||||
|
Classifier: Intended Audience :: Developers
|
||||||
|
Classifier: License :: OSI Approved :: BSD License
|
||||||
|
Classifier: Operating System :: OS Independent
|
||||||
|
Classifier: Programming Language :: Python
|
||||||
|
Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
|
||||||
|
Classifier: Topic :: Text Processing :: Markup :: HTML
|
||||||
|
Requires-Python: >=3.7
|
||||||
|
Description-Content-Type: text/x-rst
|
||||||
|
License-File: LICENSE.rst
|
||||||
|
|
||||||
|
MarkupSafe
|
||||||
|
==========
|
||||||
|
|
||||||
|
MarkupSafe implements a text object that escapes characters so it is
|
||||||
|
safe to use in HTML and XML. Characters that have special meanings are
|
||||||
|
replaced so that they display as the actual characters. This mitigates
|
||||||
|
injection attacks, meaning untrusted user input can safely be displayed
|
||||||
|
on a page.
|
||||||
|
|
||||||
|
|
||||||
|
Installing
|
||||||
|
----------
|
||||||
|
|
||||||
|
Install and update using `pip`_:
|
||||||
|
|
||||||
|
.. code-block:: text
|
||||||
|
|
||||||
|
pip install -U MarkupSafe
|
||||||
|
|
||||||
|
.. _pip: https://pip.pypa.io/en/stable/getting-started/
|
||||||
|
|
||||||
|
|
||||||
|
Examples
|
||||||
|
--------
|
||||||
|
|
||||||
|
.. code-block:: pycon
|
||||||
|
|
||||||
|
>>> from markupsafe import Markup, escape
|
||||||
|
|
||||||
|
>>> # escape replaces special characters and wraps in Markup
|
||||||
|
>>> escape("<script>alert(document.cookie);</script>")
|
||||||
|
Markup('<script>alert(document.cookie);</script>')
|
||||||
|
|
||||||
|
>>> # wrap in Markup to mark text "safe" and prevent escaping
|
||||||
|
>>> Markup("<strong>Hello</strong>")
|
||||||
|
Markup('<strong>hello</strong>')
|
||||||
|
|
||||||
|
>>> escape(Markup("<strong>Hello</strong>"))
|
||||||
|
Markup('<strong>hello</strong>')
|
||||||
|
|
||||||
|
>>> # Markup is a str subclass
|
||||||
|
>>> # methods and operators escape their arguments
|
||||||
|
>>> template = Markup("Hello <em>{name}</em>")
|
||||||
|
>>> template.format(name='"World"')
|
||||||
|
Markup('Hello <em>"World"</em>')
|
||||||
|
|
||||||
|
|
||||||
|
Donate
|
||||||
|
------
|
||||||
|
|
||||||
|
The Pallets organization develops and supports MarkupSafe and other
|
||||||
|
popular packages. In order to grow the community of contributors and
|
||||||
|
users, and allow the maintainers to devote more time to the projects,
|
||||||
|
`please donate today`_.
|
||||||
|
|
||||||
|
.. _please donate today: https://palletsprojects.com/donate
|
||||||
|
|
||||||
|
|
||||||
|
Links
|
||||||
|
-----
|
||||||
|
|
||||||
|
- Documentation: https://markupsafe.palletsprojects.com/
|
||||||
|
- Changes: https://markupsafe.palletsprojects.com/changes/
|
||||||
|
- PyPI Releases: https://pypi.org/project/MarkupSafe/
|
||||||
|
- Source Code: https://github.com/pallets/markupsafe/
|
||||||
|
- Issue Tracker: https://github.com/pallets/markupsafe/issues/
|
||||||
|
- Chat: https://discord.gg/pallets
|
@ -0,0 +1,14 @@
|
|||||||
|
MarkupSafe-2.1.5.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
|
||||||
|
MarkupSafe-2.1.5.dist-info/LICENSE.rst,sha256=SJqOEQhQntmKN7uYPhHg9-HTHwvY-Zp5yESOf_N9B-o,1475
|
||||||
|
MarkupSafe-2.1.5.dist-info/METADATA,sha256=2dRDPam6OZLfpX0wg1JN5P3u9arqACxVSfdGmsJU7o8,3003
|
||||||
|
MarkupSafe-2.1.5.dist-info/RECORD,,
|
||||||
|
MarkupSafe-2.1.5.dist-info/WHEEL,sha256=1_erwh2TCU3TrYzgBQGCtZskLEmw2vbfn7Xu2mHHvyU,111
|
||||||
|
MarkupSafe-2.1.5.dist-info/top_level.txt,sha256=qy0Plje5IJuvsCBjejJyhDCjEAdcDLK_2agVcex8Z6U,11
|
||||||
|
markupsafe/__init__.py,sha256=r7VOTjUq7EMQ4v3p4R1LoVOGJg6ysfYRncLr34laRBs,10958
|
||||||
|
markupsafe/__pycache__/__init__.cpython-312.pyc,,
|
||||||
|
markupsafe/__pycache__/_native.cpython-312.pyc,,
|
||||||
|
markupsafe/_native.py,sha256=GR86Qvo_GcgKmKreA1WmYN9ud17OFwkww8E-fiW-57s,1713
|
||||||
|
markupsafe/_speedups.c,sha256=X2XvQVtIdcK4Usz70BvkzoOfjTCmQlDkkjYSn-swE0g,7083
|
||||||
|
markupsafe/_speedups.cpython-312-darwin.so,sha256=zO55W2sOSohVnMko0CD2bITP4v6UpfeRj-x2I_8pGkA,35208
|
||||||
|
markupsafe/_speedups.pyi,sha256=vfMCsOgbAXRNLUXkyuyonG8uEWKYU4PDqNuMaDELAYw,229
|
||||||
|
markupsafe/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
@ -0,0 +1,5 @@
|
|||||||
|
Wheel-Version: 1.0
|
||||||
|
Generator: bdist_wheel (0.42.0)
|
||||||
|
Root-Is-Purelib: false
|
||||||
|
Tag: cp312-cp312-macosx_10_9_x86_64
|
||||||
|
|
@ -0,0 +1 @@
|
|||||||
|
markupsafe
|
@ -0,0 +1 @@
|
|||||||
|
pip
|
@ -0,0 +1,20 @@
|
|||||||
|
Original work Copyright (C) 2011-2018 by Hong Minhee <https://hongminhee.org>
|
||||||
|
Modified work Copyright (C) 2019-2023 by E. McConville <https://emcconville.com>
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
@ -0,0 +1,128 @@
|
|||||||
|
Metadata-Version: 2.1
|
||||||
|
Name: Wand
|
||||||
|
Version: 0.6.13
|
||||||
|
Summary: Ctypes-based simple MagickWand API binding for Python
|
||||||
|
Home-page: http://wand-py.org/
|
||||||
|
Author: Hong Minhee
|
||||||
|
Author-email: hongminhee@member.fsf.org
|
||||||
|
Maintainer: E. McConville
|
||||||
|
Maintainer-email: emcconville@emcconville.com
|
||||||
|
License: MIT License
|
||||||
|
Project-URL: Documentation, https://docs.wand-py.org
|
||||||
|
Project-URL: Source, https://github.com/emcconville/wand
|
||||||
|
Project-URL: Tracker, https://github.com/emcconville/wand/issues
|
||||||
|
Keywords: ImageMagick ctypes
|
||||||
|
Classifier: Development Status :: 5 - Production/Stable
|
||||||
|
Classifier: Intended Audience :: Developers
|
||||||
|
Classifier: License :: OSI Approved :: MIT License
|
||||||
|
Classifier: Operating System :: OS Independent
|
||||||
|
Classifier: Programming Language :: Python :: 2
|
||||||
|
Classifier: Programming Language :: Python :: 2.7
|
||||||
|
Classifier: Programming Language :: Python :: 3
|
||||||
|
Classifier: Programming Language :: Python :: 3.3
|
||||||
|
Classifier: Programming Language :: Python :: 3.4
|
||||||
|
Classifier: Programming Language :: Python :: 3.5
|
||||||
|
Classifier: Programming Language :: Python :: 3.6
|
||||||
|
Classifier: Programming Language :: Python :: 3.7
|
||||||
|
Classifier: Programming Language :: Python :: 3.8
|
||||||
|
Classifier: Programming Language :: Python :: 3.9
|
||||||
|
Classifier: Programming Language :: Python :: 3.10
|
||||||
|
Classifier: Programming Language :: Python :: 3.11
|
||||||
|
Classifier: Programming Language :: Python :: Implementation :: CPython
|
||||||
|
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
||||||
|
Classifier: Programming Language :: Python :: Implementation :: Stackless
|
||||||
|
Classifier: Topic :: Multimedia :: Graphics
|
||||||
|
Description-Content-Type: text/x-rst
|
||||||
|
License-File: LICENSE
|
||||||
|
Provides-Extra: doc
|
||||||
|
Requires-Dist: Sphinx (>=5.3.0) ; extra == 'doc'
|
||||||
|
Provides-Extra: test
|
||||||
|
Requires-Dist: pytest (>=7.2.0) ; extra == 'test'
|
||||||
|
|
||||||
|
.. image:: https://docs.wand-py.org/en/latest/_static/wand.png
|
||||||
|
:width: 120
|
||||||
|
:height: 120
|
||||||
|
|
||||||
|
Wand_
|
||||||
|
=====
|
||||||
|
|
||||||
|
Wand is a ``ctypes``-based simple ImageMagick_ binding for Python,
|
||||||
|
supporting 2.7, 3.3+, and PyPy. All functionalities of MagickWand API are
|
||||||
|
implemented in Wand.
|
||||||
|
|
||||||
|
You can install the package from PyPI_ by using ``pip``:
|
||||||
|
|
||||||
|
.. code-block:: console
|
||||||
|
|
||||||
|
$ pip install Wand
|
||||||
|
|
||||||
|
Or would you like to enjoy the bleeding edge? Check out the head
|
||||||
|
revision of the source code from the `GitHub repository`__:
|
||||||
|
|
||||||
|
.. code-block:: console
|
||||||
|
|
||||||
|
$ git clone git://github.com/emcconville/wand.git
|
||||||
|
$ cd wand/
|
||||||
|
$ python setup.py install
|
||||||
|
|
||||||
|
.. _Wand: http://wand-py.org/
|
||||||
|
.. _ImageMagick: https://www.imagemagick.org/
|
||||||
|
.. _PyPI: https://pypi.python.org/pypi/Wand
|
||||||
|
__ https://github.com/emcconville/wand
|
||||||
|
|
||||||
|
|
||||||
|
Docs
|
||||||
|
----
|
||||||
|
|
||||||
|
Recent version
|
||||||
|
https://docs.wand-py.org/
|
||||||
|
|
||||||
|
Development version
|
||||||
|
https://docs.wand-py.org/en/latest/
|
||||||
|
|
||||||
|
.. image:: https://readthedocs.org/projects/wand/badge/
|
||||||
|
:alt: Documentation Status
|
||||||
|
:target: https://docs.wand-py.org/en/latest/
|
||||||
|
|
||||||
|
|
||||||
|
Community
|
||||||
|
---------
|
||||||
|
|
||||||
|
Website
|
||||||
|
http://wand-py.org/
|
||||||
|
|
||||||
|
GitHub
|
||||||
|
https://github.com/emcconville/wand
|
||||||
|
|
||||||
|
Package Index (Cheeseshop)
|
||||||
|
https://pypi.python.org/pypi/Wand
|
||||||
|
|
||||||
|
.. image:: https://badge.fury.io/py/Wand.svg?
|
||||||
|
:alt: Latest PyPI version
|
||||||
|
:target: https://pypi.python.org/pypi/Wand
|
||||||
|
|
||||||
|
Discord
|
||||||
|
https://discord.gg/wtDWDE9fXK
|
||||||
|
|
||||||
|
Stack Overflow tag (Q&A)
|
||||||
|
http://stackoverflow.com/questions/tagged/wand
|
||||||
|
|
||||||
|
Continuous Integration (Travis CI)
|
||||||
|
https://app.travis-ci.com/emcconville/wand
|
||||||
|
|
||||||
|
.. image:: https://app.travis-ci.com/emcconville/wand.svg?branch=master
|
||||||
|
:alt: Build Status
|
||||||
|
:target: https://app.travis-ci.com/emcconville/wand
|
||||||
|
|
||||||
|
Continuous Integration (GitHub Actions)
|
||||||
|
https://github.com/emcconville/wand/actions
|
||||||
|
|
||||||
|
.. image:: https://github.com/emcconville/wand/workflows/Wand%20CI/badge.svg
|
||||||
|
:alt: Build Status
|
||||||
|
:target: https://github.com/emcconville/wand/actions?query=workflow%3A%22Wand+CI%22
|
||||||
|
|
||||||
|
Code Coverage
|
||||||
|
https://coveralls.io/r/emcconville/wand
|
||||||
|
|
||||||
|
.. image:: https://coveralls.io/repos/github/emcconville/wand/badge.svg?branch=master
|
||||||
|
:target: https://coveralls.io/github/emcconville/wand?branch=master
|
@ -0,0 +1,53 @@
|
|||||||
|
Wand-0.6.13.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
|
||||||
|
Wand-0.6.13.dist-info/LICENSE,sha256=LApHI5GF4xKeFcpRi4lLV5DPNhJG7jO9M0B0PLsdr2c,1183
|
||||||
|
Wand-0.6.13.dist-info/METADATA,sha256=oeM5ek_GiYCwvpVcIAs4jy1n3xVwMggUNWmXy1wqzA8,3963
|
||||||
|
Wand-0.6.13.dist-info/RECORD,,
|
||||||
|
Wand-0.6.13.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
||||||
|
Wand-0.6.13.dist-info/WHEEL,sha256=bb2Ot9scclHKMOLDEHY6B2sicWOgugjFKaJsT7vwMQo,110
|
||||||
|
Wand-0.6.13.dist-info/top_level.txt,sha256=uFTymN2uxamdZLu2fxZzaBcGwv7WW9v60YcsATzndig,5
|
||||||
|
wand/__init__.py,sha256=bEmSKTbdilJXM5PTgsuaqvpliBlmy2of5f77SJMKRh8,202
|
||||||
|
wand/__pycache__/__init__.cpython-312.pyc,,
|
||||||
|
wand/__pycache__/api.cpython-312.pyc,,
|
||||||
|
wand/__pycache__/assertions.cpython-312.pyc,,
|
||||||
|
wand/__pycache__/color.cpython-312.pyc,,
|
||||||
|
wand/__pycache__/compat.cpython-312.pyc,,
|
||||||
|
wand/__pycache__/display.cpython-312.pyc,,
|
||||||
|
wand/__pycache__/drawing.cpython-312.pyc,,
|
||||||
|
wand/__pycache__/exceptions.cpython-312.pyc,,
|
||||||
|
wand/__pycache__/font.cpython-312.pyc,,
|
||||||
|
wand/__pycache__/image.cpython-312.pyc,,
|
||||||
|
wand/__pycache__/resource.cpython-312.pyc,,
|
||||||
|
wand/__pycache__/sequence.cpython-312.pyc,,
|
||||||
|
wand/__pycache__/version.cpython-312.pyc,,
|
||||||
|
wand/api.py,sha256=BXkdzrPqIA0inKkAuuvBFQfjSVKvbX0vAeBLwA1o6ek,10212
|
||||||
|
wand/assertions.py,sha256=Ou1l9us4pgxhu-StOivBSMU4zoSKvcjY0WzefQtE0ZE,4721
|
||||||
|
wand/cdefs/__init__.py,sha256=YaCYVyNhimXKrD5xWLrAmaMsBAr0QrnVshC7b_vfIPE,126
|
||||||
|
wand/cdefs/__pycache__/__init__.cpython-312.pyc,,
|
||||||
|
wand/cdefs/__pycache__/core.cpython-312.pyc,,
|
||||||
|
wand/cdefs/__pycache__/drawing_wand.cpython-312.pyc,,
|
||||||
|
wand/cdefs/__pycache__/magick_image.cpython-312.pyc,,
|
||||||
|
wand/cdefs/__pycache__/magick_property.cpython-312.pyc,,
|
||||||
|
wand/cdefs/__pycache__/magick_wand.cpython-312.pyc,,
|
||||||
|
wand/cdefs/__pycache__/pixel_iterator.cpython-312.pyc,,
|
||||||
|
wand/cdefs/__pycache__/pixel_wand.cpython-312.pyc,,
|
||||||
|
wand/cdefs/__pycache__/structures.cpython-312.pyc,,
|
||||||
|
wand/cdefs/__pycache__/wandtypes.cpython-312.pyc,,
|
||||||
|
wand/cdefs/core.py,sha256=raahBqwXxAndWUd3a4K_wiwx5hP07Hm0j2SBPSs4Yys,5783
|
||||||
|
wand/cdefs/drawing_wand.py,sha256=hDIy9UnNOuCNuUj0nhelHRSTCh3Gd8Td5uu4Ng9_vQk,12343
|
||||||
|
wand/cdefs/magick_image.py,sha256=lExHUubi3qo7XB53g-r51xSJTUf1RV5M4fDtvjfxZyE,53527
|
||||||
|
wand/cdefs/magick_property.py,sha256=YdE5asyvGnmB2MiXRafGepK5sS5U0tSqWUoRm5osx7Q,8659
|
||||||
|
wand/cdefs/magick_wand.py,sha256=cXrruT_7sUfOh7J603bjJDyjgZninUjbbKmkJVRcsME,2477
|
||||||
|
wand/cdefs/pixel_iterator.py,sha256=6At0KxkCJ8XDwyud9zmMBViFG1yJqa55_9ob9jxXT2Q,1797
|
||||||
|
wand/cdefs/pixel_wand.py,sha256=3ilKZhDkB6uPa1_0ojuHI94mW5iX6Kikv5Js_60WNK4,7553
|
||||||
|
wand/cdefs/structures.py,sha256=-1KlazZv0ErnKCdQ8DMpF02AFPIbqbdlI8dlALm0-Jo,6787
|
||||||
|
wand/cdefs/wandtypes.py,sha256=0_VgrY2IurGmaRcsPYFKVDPpqekRn4upQFZEXoQqoPw,1400
|
||||||
|
wand/color.py,sha256=YaiApbRC1RoUbHd12Q7gtzYjqrnqHXuSlCoB3OjoBhM,24509
|
||||||
|
wand/compat.py,sha256=4hYn7AdKfVNxhLiazNXZsePk5HSI2ZYEmcmshVhaplY,4571
|
||||||
|
wand/display.py,sha256=mhlxoWKjGbyfliHAEbeeDdFLsgS0CYsPB91TbHfY258,2450
|
||||||
|
wand/drawing.py,sha256=dQUv8hn5iSke6Mijj10G2hvPg0Udzpghx5wexfuTkQU,80107
|
||||||
|
wand/exceptions.py,sha256=ZtD_15ij58SYXp7QXMxbXp8291vYH0k5MFQJPflICdU,11165
|
||||||
|
wand/font.py,sha256=8auFsXmnLppE6TDvopXHCg430ZK6NkqEGqEkVkaPgsk,4021
|
||||||
|
wand/image.py,sha256=5dVN50SufrIwlkmRBzU1eQVSr0OuQDVoZDy7WP2St4A,431410
|
||||||
|
wand/resource.py,sha256=NrlAzL4QnyxeQp-uZS1WT4HA1kqf1y9QJ6tluZowHmg,11805
|
||||||
|
wand/sequence.py,sha256=ewZnCuR7rOeLQTp5Ix34dxu5huiCEx5GUVjEdgDzDKU,13183
|
||||||
|
wand/version.py,sha256=N-YjDddbg9jLv_pSgBomtDGAHMFtz8pDHTWQG9HrS-o,10692
|
@ -0,0 +1,6 @@
|
|||||||
|
Wheel-Version: 1.0
|
||||||
|
Generator: bdist_wheel (0.38.4)
|
||||||
|
Root-Is-Purelib: true
|
||||||
|
Tag: py2-none-any
|
||||||
|
Tag: py3-none-any
|
||||||
|
|
@ -0,0 +1 @@
|
|||||||
|
wand
|
@ -0,0 +1 @@
|
|||||||
|
pip
|
@ -0,0 +1,27 @@
|
|||||||
|
Metadata-Version: 2.1
|
||||||
|
Name: fpdf
|
||||||
|
Version: 1.7.2
|
||||||
|
Summary: Simple PDF generation for Python
|
||||||
|
Home-page: http://code.google.com/p/pyfpdf
|
||||||
|
Download-URL: https://github.com/reingart/pyfpdf/tarball/1.7.2
|
||||||
|
Author: Olivier PLATHEY ported by Max
|
||||||
|
Author-email: maxpat78@yahoo.it
|
||||||
|
Maintainer: Mariano Reingart
|
||||||
|
Maintainer-email: reingart@gmail.com
|
||||||
|
License: LGPLv3+
|
||||||
|
Keywords: pdf,unicode,png,jpg,ttf
|
||||||
|
Classifier: Development Status :: 5 - Production/Stable
|
||||||
|
Classifier: Intended Audience :: Developers
|
||||||
|
Classifier: License :: OSI Approved :: GNU Lesser General Public License v3 (LGPLv3)
|
||||||
|
Classifier: Programming Language :: Python
|
||||||
|
Classifier: Programming Language :: Python :: 2.5
|
||||||
|
Classifier: Programming Language :: Python :: 2.6
|
||||||
|
Classifier: Programming Language :: Python :: 2.7
|
||||||
|
Classifier: Programming Language :: Python :: 3.2
|
||||||
|
Classifier: Programming Language :: Python :: 3.3
|
||||||
|
Classifier: Programming Language :: Python :: 3.4
|
||||||
|
Classifier: Operating System :: OS Independent
|
||||||
|
Classifier: Topic :: Software Development :: Libraries :: PHP Classes
|
||||||
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
||||||
|
Classifier: Topic :: Multimedia :: Graphics
|
||||||
|
|
@ -0,0 +1,22 @@
|
|||||||
|
fpdf-1.7.2.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
|
||||||
|
fpdf-1.7.2.dist-info/METADATA,sha256=uC7PCusjTBkhFZeHhnBnD3uhgg2oKFS5xQUayFX2_p0,1146
|
||||||
|
fpdf-1.7.2.dist-info/RECORD,,
|
||||||
|
fpdf-1.7.2.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
||||||
|
fpdf-1.7.2.dist-info/WHEEL,sha256=DZajD4pwLWue70CAfc7YaxT1wLUciNBvN_TTcvXpltE,110
|
||||||
|
fpdf-1.7.2.dist-info/top_level.txt,sha256=5LInphvlslEpMUNNFUFlIxUmargkp4k1WqQnoDBAF-w,5
|
||||||
|
fpdf/__init__.py,sha256=4IFfKo-doXEmaBsycnxiygWlU_mLBl8qZ_0KWu1axq0,415
|
||||||
|
fpdf/__pycache__/__init__.cpython-312.pyc,,
|
||||||
|
fpdf/__pycache__/fonts.cpython-312.pyc,,
|
||||||
|
fpdf/__pycache__/fpdf.cpython-312.pyc,,
|
||||||
|
fpdf/__pycache__/html.cpython-312.pyc,,
|
||||||
|
fpdf/__pycache__/php.cpython-312.pyc,,
|
||||||
|
fpdf/__pycache__/py3k.cpython-312.pyc,,
|
||||||
|
fpdf/__pycache__/template.cpython-312.pyc,,
|
||||||
|
fpdf/__pycache__/ttfonts.cpython-312.pyc,,
|
||||||
|
fpdf/fonts.py,sha256=zldged9bndZMJZkg9sXb1nF6vv8i7KhMBrpJMOcKDec,26573
|
||||||
|
fpdf/fpdf.py,sha256=qoNd_YEn0mBSQObG8eACOPNXDvTweJlDFfyw6LQi7vU,75624
|
||||||
|
fpdf/html.py,sha256=jYqV0oatI7e5pS4VHswH9Ue0fx9RYdn4QiFkG8Fp3X8,14733
|
||||||
|
fpdf/php.py,sha256=0UwFm1tR7DSOXH8xeNOAboaskytznL6Dpcp1UyI63yg,1516
|
||||||
|
fpdf/py3k.py,sha256=A65E5L989fKEYoEfQDYDI8-hpCQOqALjMBFyspZsvJg,1602
|
||||||
|
fpdf/template.py,sha256=8AJ_-oYLBh2ZaIOXQrFtMp9sWyZajgpjSBJDWxqkL2U,9282
|
||||||
|
fpdf/ttfonts.py,sha256=dRwaAJF563I5loy5glrw12A9GTSRpD3U-MYfZC4TbJE,40412
|
@ -0,0 +1,6 @@
|
|||||||
|
Wheel-Version: 1.0
|
||||||
|
Generator: bdist_wheel (0.43.0)
|
||||||
|
Root-Is-Purelib: true
|
||||||
|
Tag: py2-none-any
|
||||||
|
Tag: py3-none-any
|
||||||
|
|
@ -0,0 +1 @@
|
|||||||
|
fpdf
|
@ -0,0 +1,16 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
"FPDF for python"
|
||||||
|
|
||||||
|
__license__ = "LGPL 3.0"
|
||||||
|
__version__ = "1.7.2"
|
||||||
|
|
||||||
|
from .fpdf import FPDF, FPDF_FONT_DIR, FPDF_VERSION, SYSTEM_TTFONTS, set_global, FPDF_CACHE_MODE, FPDF_CACHE_DIR
|
||||||
|
try:
|
||||||
|
from .html import HTMLMixin
|
||||||
|
except ImportError:
|
||||||
|
import warnings
|
||||||
|
warnings.warn("web2py gluon package not installed, required for html2pdf")
|
||||||
|
|
||||||
|
from .template import Template
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1,156 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
# -*- coding: latin-1 -*-
|
||||||
|
|
||||||
|
# Fonts:
|
||||||
|
|
||||||
|
fpdf_charwidths = {}
|
||||||
|
|
||||||
|
fpdf_charwidths['courier']={}
|
||||||
|
|
||||||
|
for i in range(0,256):
|
||||||
|
fpdf_charwidths['courier'][chr(i)]=600
|
||||||
|
fpdf_charwidths['courierB']=fpdf_charwidths['courier']
|
||||||
|
fpdf_charwidths['courierI']=fpdf_charwidths['courier']
|
||||||
|
fpdf_charwidths['courierBI']=fpdf_charwidths['courier']
|
||||||
|
|
||||||
|
fpdf_charwidths['helvetica']={
|
||||||
|
'\x00':278,'\x01':278,'\x02':278,'\x03':278,'\x04':278,'\x05':278,'\x06':278,'\x07':278,'\x08':278,'\t':278,'\n':278,'\x0b':278,'\x0c':278,'\r':278,'\x0e':278,'\x0f':278,'\x10':278,'\x11':278,'\x12':278,'\x13':278,'\x14':278,'\x15':278,
|
||||||
|
'\x16':278,'\x17':278,'\x18':278,'\x19':278,'\x1a':278,'\x1b':278,'\x1c':278,'\x1d':278,'\x1e':278,'\x1f':278,' ':278,'!':278,'"':355,'#':556,'$':556,'%':889,'&':667,'\'':191,'(':333,')':333,'*':389,'+':584,
|
||||||
|
',':278,'-':333,'.':278,'/':278,'0':556,'1':556,'2':556,'3':556,'4':556,'5':556,'6':556,'7':556,'8':556,'9':556,':':278,';':278,'<':584,'=':584,'>':584,'?':556,'@':1015,'A':667,
|
||||||
|
'B':667,'C':722,'D':722,'E':667,'F':611,'G':778,'H':722,'I':278,'J':500,'K':667,'L':556,'M':833,'N':722,'O':778,'P':667,'Q':778,'R':722,'S':667,'T':611,'U':722,'V':667,'W':944,
|
||||||
|
'X':667,'Y':667,'Z':611,'[':278,'\\':278,']':278,'^':469,'_':556,'`':333,'a':556,'b':556,'c':500,'d':556,'e':556,'f':278,'g':556,'h':556,'i':222,'j':222,'k':500,'l':222,'m':833,
|
||||||
|
'n':556,'o':556,'p':556,'q':556,'r':333,'s':500,'t':278,'u':556,'v':500,'w':722,'x':500,'y':500,'z':500,'{':334,'|':260,'}':334,'~':584,'\x7f':350,'\x80':556,'\x81':350,'\x82':222,'\x83':556,
|
||||||
|
'\x84':333,'\x85':1000,'\x86':556,'\x87':556,'\x88':333,'\x89':1000,'\x8a':667,'\x8b':333,'\x8c':1000,'\x8d':350,'\x8e':611,'\x8f':350,'\x90':350,'\x91':222,'\x92':222,'\x93':333,'\x94':333,'\x95':350,'\x96':556,'\x97':1000,'\x98':333,'\x99':1000,
|
||||||
|
'\x9a':500,'\x9b':333,'\x9c':944,'\x9d':350,'\x9e':500,'\x9f':667,'\xa0':278,'\xa1':333,'\xa2':556,'\xa3':556,'\xa4':556,'\xa5':556,'\xa6':260,'\xa7':556,'\xa8':333,'\xa9':737,'\xaa':370,'\xab':556,'\xac':584,'\xad':333,'\xae':737,'\xaf':333,
|
||||||
|
'\xb0':400,'\xb1':584,'\xb2':333,'\xb3':333,'\xb4':333,'\xb5':556,'\xb6':537,'\xb7':278,'\xb8':333,'\xb9':333,'\xba':365,'\xbb':556,'\xbc':834,'\xbd':834,'\xbe':834,'\xbf':611,'\xc0':667,'\xc1':667,'\xc2':667,'\xc3':667,'\xc4':667,'\xc5':667,
|
||||||
|
'\xc6':1000,'\xc7':722,'\xc8':667,'\xc9':667,'\xca':667,'\xcb':667,'\xcc':278,'\xcd':278,'\xce':278,'\xcf':278,'\xd0':722,'\xd1':722,'\xd2':778,'\xd3':778,'\xd4':778,'\xd5':778,'\xd6':778,'\xd7':584,'\xd8':778,'\xd9':722,'\xda':722,'\xdb':722,
|
||||||
|
'\xdc':722,'\xdd':667,'\xde':667,'\xdf':611,'\xe0':556,'\xe1':556,'\xe2':556,'\xe3':556,'\xe4':556,'\xe5':556,'\xe6':889,'\xe7':500,'\xe8':556,'\xe9':556,'\xea':556,'\xeb':556,'\xec':278,'\xed':278,'\xee':278,'\xef':278,'\xf0':556,'\xf1':556,
|
||||||
|
'\xf2':556,'\xf3':556,'\xf4':556,'\xf5':556,'\xf6':556,'\xf7':584,'\xf8':611,'\xf9':556,'\xfa':556,'\xfb':556,'\xfc':556,'\xfd':500,'\xfe':556,'\xff':500}
|
||||||
|
|
||||||
|
fpdf_charwidths['helveticaB']={
|
||||||
|
'\x00':278,'\x01':278,'\x02':278,'\x03':278,'\x04':278,'\x05':278,'\x06':278,'\x07':278,'\x08':278,'\t':278,'\n':278,'\x0b':278,'\x0c':278,'\r':278,'\x0e':278,'\x0f':278,'\x10':278,'\x11':278,'\x12':278,'\x13':278,'\x14':278,'\x15':278,
|
||||||
|
'\x16':278,'\x17':278,'\x18':278,'\x19':278,'\x1a':278,'\x1b':278,'\x1c':278,'\x1d':278,'\x1e':278,'\x1f':278,' ':278,'!':333,'"':474,'#':556,'$':556,'%':889,'&':722,'\'':238,'(':333,')':333,'*':389,'+':584,
|
||||||
|
',':278,'-':333,'.':278,'/':278,'0':556,'1':556,'2':556,'3':556,'4':556,'5':556,'6':556,'7':556,'8':556,'9':556,':':333,';':333,'<':584,'=':584,'>':584,'?':611,'@':975,'A':722,
|
||||||
|
'B':722,'C':722,'D':722,'E':667,'F':611,'G':778,'H':722,'I':278,'J':556,'K':722,'L':611,'M':833,'N':722,'O':778,'P':667,'Q':778,'R':722,'S':667,'T':611,'U':722,'V':667,'W':944,
|
||||||
|
'X':667,'Y':667,'Z':611,'[':333,'\\':278,']':333,'^':584,'_':556,'`':333,'a':556,'b':611,'c':556,'d':611,'e':556,'f':333,'g':611,'h':611,'i':278,'j':278,'k':556,'l':278,'m':889,
|
||||||
|
'n':611,'o':611,'p':611,'q':611,'r':389,'s':556,'t':333,'u':611,'v':556,'w':778,'x':556,'y':556,'z':500,'{':389,'|':280,'}':389,'~':584,'\x7f':350,'\x80':556,'\x81':350,'\x82':278,'\x83':556,
|
||||||
|
'\x84':500,'\x85':1000,'\x86':556,'\x87':556,'\x88':333,'\x89':1000,'\x8a':667,'\x8b':333,'\x8c':1000,'\x8d':350,'\x8e':611,'\x8f':350,'\x90':350,'\x91':278,'\x92':278,'\x93':500,'\x94':500,'\x95':350,'\x96':556,'\x97':1000,'\x98':333,'\x99':1000,
|
||||||
|
'\x9a':556,'\x9b':333,'\x9c':944,'\x9d':350,'\x9e':500,'\x9f':667,'\xa0':278,'\xa1':333,'\xa2':556,'\xa3':556,'\xa4':556,'\xa5':556,'\xa6':280,'\xa7':556,'\xa8':333,'\xa9':737,'\xaa':370,'\xab':556,'\xac':584,'\xad':333,'\xae':737,'\xaf':333,
|
||||||
|
'\xb0':400,'\xb1':584,'\xb2':333,'\xb3':333,'\xb4':333,'\xb5':611,'\xb6':556,'\xb7':278,'\xb8':333,'\xb9':333,'\xba':365,'\xbb':556,'\xbc':834,'\xbd':834,'\xbe':834,'\xbf':611,'\xc0':722,'\xc1':722,'\xc2':722,'\xc3':722,'\xc4':722,'\xc5':722,
|
||||||
|
'\xc6':1000,'\xc7':722,'\xc8':667,'\xc9':667,'\xca':667,'\xcb':667,'\xcc':278,'\xcd':278,'\xce':278,'\xcf':278,'\xd0':722,'\xd1':722,'\xd2':778,'\xd3':778,'\xd4':778,'\xd5':778,'\xd6':778,'\xd7':584,'\xd8':778,'\xd9':722,'\xda':722,'\xdb':722,
|
||||||
|
'\xdc':722,'\xdd':667,'\xde':667,'\xdf':611,'\xe0':556,'\xe1':556,'\xe2':556,'\xe3':556,'\xe4':556,'\xe5':556,'\xe6':889,'\xe7':556,'\xe8':556,'\xe9':556,'\xea':556,'\xeb':556,'\xec':278,'\xed':278,'\xee':278,'\xef':278,'\xf0':611,'\xf1':611,
|
||||||
|
'\xf2':611,'\xf3':611,'\xf4':611,'\xf5':611,'\xf6':611,'\xf7':584,'\xf8':611,'\xf9':611,'\xfa':611,'\xfb':611,'\xfc':611,'\xfd':556,'\xfe':611,'\xff':556
|
||||||
|
}
|
||||||
|
|
||||||
|
fpdf_charwidths['helveticaBI']={
|
||||||
|
'\x00':278,'\x01':278,'\x02':278,'\x03':278,'\x04':278,'\x05':278,'\x06':278,'\x07':278,'\x08':278,'\t':278,'\n':278,'\x0b':278,'\x0c':278,'\r':278,'\x0e':278,'\x0f':278,'\x10':278,'\x11':278,'\x12':278,'\x13':278,'\x14':278,'\x15':278,
|
||||||
|
'\x16':278,'\x17':278,'\x18':278,'\x19':278,'\x1a':278,'\x1b':278,'\x1c':278,'\x1d':278,'\x1e':278,'\x1f':278,' ':278,'!':333,'"':474,'#':556,'$':556,'%':889,'&':722,'\'':238,'(':333,')':333,'*':389,'+':584,
|
||||||
|
',':278,'-':333,'.':278,'/':278,'0':556,'1':556,'2':556,'3':556,'4':556,'5':556,'6':556,'7':556,'8':556,'9':556,':':333,';':333,'<':584,'=':584,'>':584,'?':611,'@':975,'A':722,
|
||||||
|
'B':722,'C':722,'D':722,'E':667,'F':611,'G':778,'H':722,'I':278,'J':556,'K':722,'L':611,'M':833,'N':722,'O':778,'P':667,'Q':778,'R':722,'S':667,'T':611,'U':722,'V':667,'W':944,
|
||||||
|
'X':667,'Y':667,'Z':611,'[':333,'\\':278,']':333,'^':584,'_':556,'`':333,'a':556,'b':611,'c':556,'d':611,'e':556,'f':333,'g':611,'h':611,'i':278,'j':278,'k':556,'l':278,'m':889,
|
||||||
|
'n':611,'o':611,'p':611,'q':611,'r':389,'s':556,'t':333,'u':611,'v':556,'w':778,'x':556,'y':556,'z':500,'{':389,'|':280,'}':389,'~':584,'\x7f':350,'\x80':556,'\x81':350,'\x82':278,'\x83':556,
|
||||||
|
'\x84':500,'\x85':1000,'\x86':556,'\x87':556,'\x88':333,'\x89':1000,'\x8a':667,'\x8b':333,'\x8c':1000,'\x8d':350,'\x8e':611,'\x8f':350,'\x90':350,'\x91':278,'\x92':278,'\x93':500,'\x94':500,'\x95':350,'\x96':556,'\x97':1000,'\x98':333,'\x99':1000,
|
||||||
|
'\x9a':556,'\x9b':333,'\x9c':944,'\x9d':350,'\x9e':500,'\x9f':667,'\xa0':278,'\xa1':333,'\xa2':556,'\xa3':556,'\xa4':556,'\xa5':556,'\xa6':280,'\xa7':556,'\xa8':333,'\xa9':737,'\xaa':370,'\xab':556,'\xac':584,'\xad':333,'\xae':737,'\xaf':333,
|
||||||
|
'\xb0':400,'\xb1':584,'\xb2':333,'\xb3':333,'\xb4':333,'\xb5':611,'\xb6':556,'\xb7':278,'\xb8':333,'\xb9':333,'\xba':365,'\xbb':556,'\xbc':834,'\xbd':834,'\xbe':834,'\xbf':611,'\xc0':722,'\xc1':722,'\xc2':722,'\xc3':722,'\xc4':722,'\xc5':722,
|
||||||
|
'\xc6':1000,'\xc7':722,'\xc8':667,'\xc9':667,'\xca':667,'\xcb':667,'\xcc':278,'\xcd':278,'\xce':278,'\xcf':278,'\xd0':722,'\xd1':722,'\xd2':778,'\xd3':778,'\xd4':778,'\xd5':778,'\xd6':778,'\xd7':584,'\xd8':778,'\xd9':722,'\xda':722,'\xdb':722,
|
||||||
|
'\xdc':722,'\xdd':667,'\xde':667,'\xdf':611,'\xe0':556,'\xe1':556,'\xe2':556,'\xe3':556,'\xe4':556,'\xe5':556,'\xe6':889,'\xe7':556,'\xe8':556,'\xe9':556,'\xea':556,'\xeb':556,'\xec':278,'\xed':278,'\xee':278,'\xef':278,'\xf0':611,'\xf1':611,
|
||||||
|
'\xf2':611,'\xf3':611,'\xf4':611,'\xf5':611,'\xf6':611,'\xf7':584,'\xf8':611,'\xf9':611,'\xfa':611,'\xfb':611,'\xfc':611,'\xfd':556,'\xfe':611,'\xff':556}
|
||||||
|
|
||||||
|
fpdf_charwidths['helveticaI']={
|
||||||
|
'\x00':278,'\x01':278,'\x02':278,'\x03':278,'\x04':278,'\x05':278,'\x06':278,'\x07':278,'\x08':278,'\t':278,'\n':278,'\x0b':278,'\x0c':278,'\r':278,'\x0e':278,'\x0f':278,'\x10':278,'\x11':278,'\x12':278,'\x13':278,'\x14':278,'\x15':278,
|
||||||
|
'\x16':278,'\x17':278,'\x18':278,'\x19':278,'\x1a':278,'\x1b':278,'\x1c':278,'\x1d':278,'\x1e':278,'\x1f':278,' ':278,'!':278,'"':355,'#':556,'$':556,'%':889,'&':667,'\'':191,'(':333,')':333,'*':389,'+':584,
|
||||||
|
',':278,'-':333,'.':278,'/':278,'0':556,'1':556,'2':556,'3':556,'4':556,'5':556,'6':556,'7':556,'8':556,'9':556,':':278,';':278,'<':584,'=':584,'>':584,'?':556,'@':1015,'A':667,
|
||||||
|
'B':667,'C':722,'D':722,'E':667,'F':611,'G':778,'H':722,'I':278,'J':500,'K':667,'L':556,'M':833,'N':722,'O':778,'P':667,'Q':778,'R':722,'S':667,'T':611,'U':722,'V':667,'W':944,
|
||||||
|
'X':667,'Y':667,'Z':611,'[':278,'\\':278,']':278,'^':469,'_':556,'`':333,'a':556,'b':556,'c':500,'d':556,'e':556,'f':278,'g':556,'h':556,'i':222,'j':222,'k':500,'l':222,'m':833,
|
||||||
|
'n':556,'o':556,'p':556,'q':556,'r':333,'s':500,'t':278,'u':556,'v':500,'w':722,'x':500,'y':500,'z':500,'{':334,'|':260,'}':334,'~':584,'\x7f':350,'\x80':556,'\x81':350,'\x82':222,'\x83':556,
|
||||||
|
'\x84':333,'\x85':1000,'\x86':556,'\x87':556,'\x88':333,'\x89':1000,'\x8a':667,'\x8b':333,'\x8c':1000,'\x8d':350,'\x8e':611,'\x8f':350,'\x90':350,'\x91':222,'\x92':222,'\x93':333,'\x94':333,'\x95':350,'\x96':556,'\x97':1000,'\x98':333,'\x99':1000,
|
||||||
|
'\x9a':500,'\x9b':333,'\x9c':944,'\x9d':350,'\x9e':500,'\x9f':667,'\xa0':278,'\xa1':333,'\xa2':556,'\xa3':556,'\xa4':556,'\xa5':556,'\xa6':260,'\xa7':556,'\xa8':333,'\xa9':737,'\xaa':370,'\xab':556,'\xac':584,'\xad':333,'\xae':737,'\xaf':333,
|
||||||
|
'\xb0':400,'\xb1':584,'\xb2':333,'\xb3':333,'\xb4':333,'\xb5':556,'\xb6':537,'\xb7':278,'\xb8':333,'\xb9':333,'\xba':365,'\xbb':556,'\xbc':834,'\xbd':834,'\xbe':834,'\xbf':611,'\xc0':667,'\xc1':667,'\xc2':667,'\xc3':667,'\xc4':667,'\xc5':667,
|
||||||
|
'\xc6':1000,'\xc7':722,'\xc8':667,'\xc9':667,'\xca':667,'\xcb':667,'\xcc':278,'\xcd':278,'\xce':278,'\xcf':278,'\xd0':722,'\xd1':722,'\xd2':778,'\xd3':778,'\xd4':778,'\xd5':778,'\xd6':778,'\xd7':584,'\xd8':778,'\xd9':722,'\xda':722,'\xdb':722,
|
||||||
|
'\xdc':722,'\xdd':667,'\xde':667,'\xdf':611,'\xe0':556,'\xe1':556,'\xe2':556,'\xe3':556,'\xe4':556,'\xe5':556,'\xe6':889,'\xe7':500,'\xe8':556,'\xe9':556,'\xea':556,'\xeb':556,'\xec':278,'\xed':278,'\xee':278,'\xef':278,'\xf0':556,'\xf1':556,
|
||||||
|
'\xf2':556,'\xf3':556,'\xf4':556,'\xf5':556,'\xf6':556,'\xf7':584,'\xf8':611,'\xf9':556,'\xfa':556,'\xfb':556,'\xfc':556,'\xfd':500,'\xfe':556,'\xff':500}
|
||||||
|
|
||||||
|
fpdf_charwidths['symbol']={
|
||||||
|
'\x00':250,'\x01':250,'\x02':250,'\x03':250,'\x04':250,'\x05':250,'\x06':250,'\x07':250,'\x08':250,'\t':250,'\n':250,'\x0b':250,'\x0c':250,'\r':250,'\x0e':250,'\x0f':250,'\x10':250,'\x11':250,'\x12':250,'\x13':250,'\x14':250,'\x15':250,
|
||||||
|
'\x16':250,'\x17':250,'\x18':250,'\x19':250,'\x1a':250,'\x1b':250,'\x1c':250,'\x1d':250,'\x1e':250,'\x1f':250,' ':250,'!':333,'"':713,'#':500,'$':549,'%':833,'&':778,'\'':439,'(':333,')':333,'*':500,'+':549,
|
||||||
|
',':250,'-':549,'.':250,'/':278,'0':500,'1':500,'2':500,'3':500,'4':500,'5':500,'6':500,'7':500,'8':500,'9':500,':':278,';':278,'<':549,'=':549,'>':549,'?':444,'@':549,'A':722,
|
||||||
|
'B':667,'C':722,'D':612,'E':611,'F':763,'G':603,'H':722,'I':333,'J':631,'K':722,'L':686,'M':889,'N':722,'O':722,'P':768,'Q':741,'R':556,'S':592,'T':611,'U':690,'V':439,'W':768,
|
||||||
|
'X':645,'Y':795,'Z':611,'[':333,'\\':863,']':333,'^':658,'_':500,'`':500,'a':631,'b':549,'c':549,'d':494,'e':439,'f':521,'g':411,'h':603,'i':329,'j':603,'k':549,'l':549,'m':576,
|
||||||
|
'n':521,'o':549,'p':549,'q':521,'r':549,'s':603,'t':439,'u':576,'v':713,'w':686,'x':493,'y':686,'z':494,'{':480,'|':200,'}':480,'~':549,'\x7f':0,'\x80':0,'\x81':0,'\x82':0,'\x83':0,
|
||||||
|
'\x84':0,'\x85':0,'\x86':0,'\x87':0,'\x88':0,'\x89':0,'\x8a':0,'\x8b':0,'\x8c':0,'\x8d':0,'\x8e':0,'\x8f':0,'\x90':0,'\x91':0,'\x92':0,'\x93':0,'\x94':0,'\x95':0,'\x96':0,'\x97':0,'\x98':0,'\x99':0,
|
||||||
|
'\x9a':0,'\x9b':0,'\x9c':0,'\x9d':0,'\x9e':0,'\x9f':0,'\xa0':750,'\xa1':620,'\xa2':247,'\xa3':549,'\xa4':167,'\xa5':713,'\xa6':500,'\xa7':753,'\xa8':753,'\xa9':753,'\xaa':753,'\xab':1042,'\xac':987,'\xad':603,'\xae':987,'\xaf':603,
|
||||||
|
'\xb0':400,'\xb1':549,'\xb2':411,'\xb3':549,'\xb4':549,'\xb5':713,'\xb6':494,'\xb7':460,'\xb8':549,'\xb9':549,'\xba':549,'\xbb':549,'\xbc':1000,'\xbd':603,'\xbe':1000,'\xbf':658,'\xc0':823,'\xc1':686,'\xc2':795,'\xc3':987,'\xc4':768,'\xc5':768,
|
||||||
|
'\xc6':823,'\xc7':768,'\xc8':768,'\xc9':713,'\xca':713,'\xcb':713,'\xcc':713,'\xcd':713,'\xce':713,'\xcf':713,'\xd0':768,'\xd1':713,'\xd2':790,'\xd3':790,'\xd4':890,'\xd5':823,'\xd6':549,'\xd7':250,'\xd8':713,'\xd9':603,'\xda':603,'\xdb':1042,
|
||||||
|
'\xdc':987,'\xdd':603,'\xde':987,'\xdf':603,'\xe0':494,'\xe1':329,'\xe2':790,'\xe3':790,'\xe4':786,'\xe5':713,'\xe6':384,'\xe7':384,'\xe8':384,'\xe9':384,'\xea':384,'\xeb':384,'\xec':494,'\xed':494,'\xee':494,'\xef':494,'\xf0':0,'\xf1':329,
|
||||||
|
'\xf2':274,'\xf3':686,'\xf4':686,'\xf5':686,'\xf6':384,'\xf7':384,'\xf8':384,'\xf9':384,'\xfa':384,'\xfb':384,'\xfc':494,'\xfd':494,'\xfe':494,'\xff':0}
|
||||||
|
|
||||||
|
fpdf_charwidths['times']={
|
||||||
|
'\x00':250,'\x01':250,'\x02':250,'\x03':250,'\x04':250,'\x05':250,'\x06':250,'\x07':250,'\x08':250,'\t':250,'\n':250,'\x0b':250,'\x0c':250,'\r':250,'\x0e':250,'\x0f':250,'\x10':250,'\x11':250,'\x12':250,'\x13':250,'\x14':250,'\x15':250,
|
||||||
|
'\x16':250,'\x17':250,'\x18':250,'\x19':250,'\x1a':250,'\x1b':250,'\x1c':250,'\x1d':250,'\x1e':250,'\x1f':250,' ':250,'!':333,'"':408,'#':500,'$':500,'%':833,'&':778,'\'':180,'(':333,')':333,'*':500,'+':564,
|
||||||
|
',':250,'-':333,'.':250,'/':278,'0':500,'1':500,'2':500,'3':500,'4':500,'5':500,'6':500,'7':500,'8':500,'9':500,':':278,';':278,'<':564,'=':564,'>':564,'?':444,'@':921,'A':722,
|
||||||
|
'B':667,'C':667,'D':722,'E':611,'F':556,'G':722,'H':722,'I':333,'J':389,'K':722,'L':611,'M':889,'N':722,'O':722,'P':556,'Q':722,'R':667,'S':556,'T':611,'U':722,'V':722,'W':944,
|
||||||
|
'X':722,'Y':722,'Z':611,'[':333,'\\':278,']':333,'^':469,'_':500,'`':333,'a':444,'b':500,'c':444,'d':500,'e':444,'f':333,'g':500,'h':500,'i':278,'j':278,'k':500,'l':278,'m':778,
|
||||||
|
'n':500,'o':500,'p':500,'q':500,'r':333,'s':389,'t':278,'u':500,'v':500,'w':722,'x':500,'y':500,'z':444,'{':480,'|':200,'}':480,'~':541,'\x7f':350,'\x80':500,'\x81':350,'\x82':333,'\x83':500,
|
||||||
|
'\x84':444,'\x85':1000,'\x86':500,'\x87':500,'\x88':333,'\x89':1000,'\x8a':556,'\x8b':333,'\x8c':889,'\x8d':350,'\x8e':611,'\x8f':350,'\x90':350,'\x91':333,'\x92':333,'\x93':444,'\x94':444,'\x95':350,'\x96':500,'\x97':1000,'\x98':333,'\x99':980,
|
||||||
|
'\x9a':389,'\x9b':333,'\x9c':722,'\x9d':350,'\x9e':444,'\x9f':722,'\xa0':250,'\xa1':333,'\xa2':500,'\xa3':500,'\xa4':500,'\xa5':500,'\xa6':200,'\xa7':500,'\xa8':333,'\xa9':760,'\xaa':276,'\xab':500,'\xac':564,'\xad':333,'\xae':760,'\xaf':333,
|
||||||
|
'\xb0':400,'\xb1':564,'\xb2':300,'\xb3':300,'\xb4':333,'\xb5':500,'\xb6':453,'\xb7':250,'\xb8':333,'\xb9':300,'\xba':310,'\xbb':500,'\xbc':750,'\xbd':750,'\xbe':750,'\xbf':444,'\xc0':722,'\xc1':722,'\xc2':722,'\xc3':722,'\xc4':722,'\xc5':722,
|
||||||
|
'\xc6':889,'\xc7':667,'\xc8':611,'\xc9':611,'\xca':611,'\xcb':611,'\xcc':333,'\xcd':333,'\xce':333,'\xcf':333,'\xd0':722,'\xd1':722,'\xd2':722,'\xd3':722,'\xd4':722,'\xd5':722,'\xd6':722,'\xd7':564,'\xd8':722,'\xd9':722,'\xda':722,'\xdb':722,
|
||||||
|
'\xdc':722,'\xdd':722,'\xde':556,'\xdf':500,'\xe0':444,'\xe1':444,'\xe2':444,'\xe3':444,'\xe4':444,'\xe5':444,'\xe6':667,'\xe7':444,'\xe8':444,'\xe9':444,'\xea':444,'\xeb':444,'\xec':278,'\xed':278,'\xee':278,'\xef':278,'\xf0':500,'\xf1':500,
|
||||||
|
'\xf2':500,'\xf3':500,'\xf4':500,'\xf5':500,'\xf6':500,'\xf7':564,'\xf8':500,'\xf9':500,'\xfa':500,'\xfb':500,'\xfc':500,'\xfd':500,'\xfe':500,'\xff':500}
|
||||||
|
|
||||||
|
fpdf_charwidths['timesB']={
|
||||||
|
'\x00':250,'\x01':250,'\x02':250,'\x03':250,'\x04':250,'\x05':250,'\x06':250,'\x07':250,'\x08':250,'\t':250,'\n':250,'\x0b':250,'\x0c':250,'\r':250,'\x0e':250,'\x0f':250,'\x10':250,'\x11':250,'\x12':250,'\x13':250,'\x14':250,'\x15':250,
|
||||||
|
'\x16':250,'\x17':250,'\x18':250,'\x19':250,'\x1a':250,'\x1b':250,'\x1c':250,'\x1d':250,'\x1e':250,'\x1f':250,' ':250,'!':333,'"':555,'#':500,'$':500,'%':1000,'&':833,'\'':278,'(':333,')':333,'*':500,'+':570,
|
||||||
|
',':250,'-':333,'.':250,'/':278,'0':500,'1':500,'2':500,'3':500,'4':500,'5':500,'6':500,'7':500,'8':500,'9':500,':':333,';':333,'<':570,'=':570,'>':570,'?':500,'@':930,'A':722,
|
||||||
|
'B':667,'C':722,'D':722,'E':667,'F':611,'G':778,'H':778,'I':389,'J':500,'K':778,'L':667,'M':944,'N':722,'O':778,'P':611,'Q':778,'R':722,'S':556,'T':667,'U':722,'V':722,'W':1000,
|
||||||
|
'X':722,'Y':722,'Z':667,'[':333,'\\':278,']':333,'^':581,'_':500,'`':333,'a':500,'b':556,'c':444,'d':556,'e':444,'f':333,'g':500,'h':556,'i':278,'j':333,'k':556,'l':278,'m':833,
|
||||||
|
'n':556,'o':500,'p':556,'q':556,'r':444,'s':389,'t':333,'u':556,'v':500,'w':722,'x':500,'y':500,'z':444,'{':394,'|':220,'}':394,'~':520,'\x7f':350,'\x80':500,'\x81':350,'\x82':333,'\x83':500,
|
||||||
|
'\x84':500,'\x85':1000,'\x86':500,'\x87':500,'\x88':333,'\x89':1000,'\x8a':556,'\x8b':333,'\x8c':1000,'\x8d':350,'\x8e':667,'\x8f':350,'\x90':350,'\x91':333,'\x92':333,'\x93':500,'\x94':500,'\x95':350,'\x96':500,'\x97':1000,'\x98':333,'\x99':1000,
|
||||||
|
'\x9a':389,'\x9b':333,'\x9c':722,'\x9d':350,'\x9e':444,'\x9f':722,'\xa0':250,'\xa1':333,'\xa2':500,'\xa3':500,'\xa4':500,'\xa5':500,'\xa6':220,'\xa7':500,'\xa8':333,'\xa9':747,'\xaa':300,'\xab':500,'\xac':570,'\xad':333,'\xae':747,'\xaf':333,
|
||||||
|
'\xb0':400,'\xb1':570,'\xb2':300,'\xb3':300,'\xb4':333,'\xb5':556,'\xb6':540,'\xb7':250,'\xb8':333,'\xb9':300,'\xba':330,'\xbb':500,'\xbc':750,'\xbd':750,'\xbe':750,'\xbf':500,'\xc0':722,'\xc1':722,'\xc2':722,'\xc3':722,'\xc4':722,'\xc5':722,
|
||||||
|
'\xc6':1000,'\xc7':722,'\xc8':667,'\xc9':667,'\xca':667,'\xcb':667,'\xcc':389,'\xcd':389,'\xce':389,'\xcf':389,'\xd0':722,'\xd1':722,'\xd2':778,'\xd3':778,'\xd4':778,'\xd5':778,'\xd6':778,'\xd7':570,'\xd8':778,'\xd9':722,'\xda':722,'\xdb':722,
|
||||||
|
'\xdc':722,'\xdd':722,'\xde':611,'\xdf':556,'\xe0':500,'\xe1':500,'\xe2':500,'\xe3':500,'\xe4':500,'\xe5':500,'\xe6':722,'\xe7':444,'\xe8':444,'\xe9':444,'\xea':444,'\xeb':444,'\xec':278,'\xed':278,'\xee':278,'\xef':278,'\xf0':500,'\xf1':556,
|
||||||
|
'\xf2':500,'\xf3':500,'\xf4':500,'\xf5':500,'\xf6':500,'\xf7':570,'\xf8':500,'\xf9':556,'\xfa':556,'\xfb':556,'\xfc':556,'\xfd':500,'\xfe':556,'\xff':500}
|
||||||
|
|
||||||
|
fpdf_charwidths['timesBI']={
|
||||||
|
'\x00':250,'\x01':250,'\x02':250,'\x03':250,'\x04':250,'\x05':250,'\x06':250,'\x07':250,'\x08':250,'\t':250,'\n':250,'\x0b':250,'\x0c':250,'\r':250,'\x0e':250,'\x0f':250,'\x10':250,'\x11':250,'\x12':250,'\x13':250,'\x14':250,'\x15':250,
|
||||||
|
'\x16':250,'\x17':250,'\x18':250,'\x19':250,'\x1a':250,'\x1b':250,'\x1c':250,'\x1d':250,'\x1e':250,'\x1f':250,' ':250,'!':389,'"':555,'#':500,'$':500,'%':833,'&':778,'\'':278,'(':333,')':333,'*':500,'+':570,
|
||||||
|
',':250,'-':333,'.':250,'/':278,'0':500,'1':500,'2':500,'3':500,'4':500,'5':500,'6':500,'7':500,'8':500,'9':500,':':333,';':333,'<':570,'=':570,'>':570,'?':500,'@':832,'A':667,
|
||||||
|
'B':667,'C':667,'D':722,'E':667,'F':667,'G':722,'H':778,'I':389,'J':500,'K':667,'L':611,'M':889,'N':722,'O':722,'P':611,'Q':722,'R':667,'S':556,'T':611,'U':722,'V':667,'W':889,
|
||||||
|
'X':667,'Y':611,'Z':611,'[':333,'\\':278,']':333,'^':570,'_':500,'`':333,'a':500,'b':500,'c':444,'d':500,'e':444,'f':333,'g':500,'h':556,'i':278,'j':278,'k':500,'l':278,'m':778,
|
||||||
|
'n':556,'o':500,'p':500,'q':500,'r':389,'s':389,'t':278,'u':556,'v':444,'w':667,'x':500,'y':444,'z':389,'{':348,'|':220,'}':348,'~':570,'\x7f':350,'\x80':500,'\x81':350,'\x82':333,'\x83':500,
|
||||||
|
'\x84':500,'\x85':1000,'\x86':500,'\x87':500,'\x88':333,'\x89':1000,'\x8a':556,'\x8b':333,'\x8c':944,'\x8d':350,'\x8e':611,'\x8f':350,'\x90':350,'\x91':333,'\x92':333,'\x93':500,'\x94':500,'\x95':350,'\x96':500,'\x97':1000,'\x98':333,'\x99':1000,
|
||||||
|
'\x9a':389,'\x9b':333,'\x9c':722,'\x9d':350,'\x9e':389,'\x9f':611,'\xa0':250,'\xa1':389,'\xa2':500,'\xa3':500,'\xa4':500,'\xa5':500,'\xa6':220,'\xa7':500,'\xa8':333,'\xa9':747,'\xaa':266,'\xab':500,'\xac':606,'\xad':333,'\xae':747,'\xaf':333,
|
||||||
|
'\xb0':400,'\xb1':570,'\xb2':300,'\xb3':300,'\xb4':333,'\xb5':576,'\xb6':500,'\xb7':250,'\xb8':333,'\xb9':300,'\xba':300,'\xbb':500,'\xbc':750,'\xbd':750,'\xbe':750,'\xbf':500,'\xc0':667,'\xc1':667,'\xc2':667,'\xc3':667,'\xc4':667,'\xc5':667,
|
||||||
|
'\xc6':944,'\xc7':667,'\xc8':667,'\xc9':667,'\xca':667,'\xcb':667,'\xcc':389,'\xcd':389,'\xce':389,'\xcf':389,'\xd0':722,'\xd1':722,'\xd2':722,'\xd3':722,'\xd4':722,'\xd5':722,'\xd6':722,'\xd7':570,'\xd8':722,'\xd9':722,'\xda':722,'\xdb':722,
|
||||||
|
'\xdc':722,'\xdd':611,'\xde':611,'\xdf':500,'\xe0':500,'\xe1':500,'\xe2':500,'\xe3':500,'\xe4':500,'\xe5':500,'\xe6':722,'\xe7':444,'\xe8':444,'\xe9':444,'\xea':444,'\xeb':444,'\xec':278,'\xed':278,'\xee':278,'\xef':278,'\xf0':500,'\xf1':556,
|
||||||
|
'\xf2':500,'\xf3':500,'\xf4':500,'\xf5':500,'\xf6':500,'\xf7':570,'\xf8':500,'\xf9':556,'\xfa':556,'\xfb':556,'\xfc':556,'\xfd':444,'\xfe':500,'\xff':444}
|
||||||
|
|
||||||
|
fpdf_charwidths['timesI']={
|
||||||
|
'\x00':250,'\x01':250,'\x02':250,'\x03':250,'\x04':250,'\x05':250,'\x06':250,'\x07':250,'\x08':250,'\t':250,'\n':250,'\x0b':250,'\x0c':250,'\r':250,'\x0e':250,'\x0f':250,'\x10':250,'\x11':250,'\x12':250,'\x13':250,'\x14':250,'\x15':250,
|
||||||
|
'\x16':250,'\x17':250,'\x18':250,'\x19':250,'\x1a':250,'\x1b':250,'\x1c':250,'\x1d':250,'\x1e':250,'\x1f':250,' ':250,'!':333,'"':420,'#':500,'$':500,'%':833,'&':778,'\'':214,'(':333,')':333,'*':500,'+':675,
|
||||||
|
',':250,'-':333,'.':250,'/':278,'0':500,'1':500,'2':500,'3':500,'4':500,'5':500,'6':500,'7':500,'8':500,'9':500,':':333,';':333,'<':675,'=':675,'>':675,'?':500,'@':920,'A':611,
|
||||||
|
'B':611,'C':667,'D':722,'E':611,'F':611,'G':722,'H':722,'I':333,'J':444,'K':667,'L':556,'M':833,'N':667,'O':722,'P':611,'Q':722,'R':611,'S':500,'T':556,'U':722,'V':611,'W':833,
|
||||||
|
'X':611,'Y':556,'Z':556,'[':389,'\\':278,']':389,'^':422,'_':500,'`':333,'a':500,'b':500,'c':444,'d':500,'e':444,'f':278,'g':500,'h':500,'i':278,'j':278,'k':444,'l':278,'m':722,
|
||||||
|
'n':500,'o':500,'p':500,'q':500,'r':389,'s':389,'t':278,'u':500,'v':444,'w':667,'x':444,'y':444,'z':389,'{':400,'|':275,'}':400,'~':541,'\x7f':350,'\x80':500,'\x81':350,'\x82':333,'\x83':500,
|
||||||
|
'\x84':556,'\x85':889,'\x86':500,'\x87':500,'\x88':333,'\x89':1000,'\x8a':500,'\x8b':333,'\x8c':944,'\x8d':350,'\x8e':556,'\x8f':350,'\x90':350,'\x91':333,'\x92':333,'\x93':556,'\x94':556,'\x95':350,'\x96':500,'\x97':889,'\x98':333,'\x99':980,
|
||||||
|
'\x9a':389,'\x9b':333,'\x9c':667,'\x9d':350,'\x9e':389,'\x9f':556,'\xa0':250,'\xa1':389,'\xa2':500,'\xa3':500,'\xa4':500,'\xa5':500,'\xa6':275,'\xa7':500,'\xa8':333,'\xa9':760,'\xaa':276,'\xab':500,'\xac':675,'\xad':333,'\xae':760,'\xaf':333,
|
||||||
|
'\xb0':400,'\xb1':675,'\xb2':300,'\xb3':300,'\xb4':333,'\xb5':500,'\xb6':523,'\xb7':250,'\xb8':333,'\xb9':300,'\xba':310,'\xbb':500,'\xbc':750,'\xbd':750,'\xbe':750,'\xbf':500,'\xc0':611,'\xc1':611,'\xc2':611,'\xc3':611,'\xc4':611,'\xc5':611,
|
||||||
|
'\xc6':889,'\xc7':667,'\xc8':611,'\xc9':611,'\xca':611,'\xcb':611,'\xcc':333,'\xcd':333,'\xce':333,'\xcf':333,'\xd0':722,'\xd1':667,'\xd2':722,'\xd3':722,'\xd4':722,'\xd5':722,'\xd6':722,'\xd7':675,'\xd8':722,'\xd9':722,'\xda':722,'\xdb':722,
|
||||||
|
'\xdc':722,'\xdd':556,'\xde':611,'\xdf':500,'\xe0':500,'\xe1':500,'\xe2':500,'\xe3':500,'\xe4':500,'\xe5':500,'\xe6':667,'\xe7':444,'\xe8':444,'\xe9':444,'\xea':444,'\xeb':444,'\xec':278,'\xed':278,'\xee':278,'\xef':278,'\xf0':500,'\xf1':500,
|
||||||
|
'\xf2':500,'\xf3':500,'\xf4':500,'\xf5':500,'\xf6':500,'\xf7':675,'\xf8':500,'\xf9':500,'\xfa':500,'\xfb':500,'\xfc':500,'\xfd':444,'\xfe':500,'\xff':444}
|
||||||
|
|
||||||
|
fpdf_charwidths['zapfdingbats']={
|
||||||
|
'\x00':0,'\x01':0,'\x02':0,'\x03':0,'\x04':0,'\x05':0,'\x06':0,'\x07':0,'\x08':0,'\t':0,'\n':0,'\x0b':0,'\x0c':0,'\r':0,'\x0e':0,'\x0f':0,'\x10':0,'\x11':0,'\x12':0,'\x13':0,'\x14':0,'\x15':0,
|
||||||
|
'\x16':0,'\x17':0,'\x18':0,'\x19':0,'\x1a':0,'\x1b':0,'\x1c':0,'\x1d':0,'\x1e':0,'\x1f':0,' ':278,'!':974,'"':961,'#':974,'$':980,'%':719,'&':789,'\'':790,'(':791,')':690,'*':960,'+':939,
|
||||||
|
',':549,'-':855,'.':911,'/':933,'0':911,'1':945,'2':974,'3':755,'4':846,'5':762,'6':761,'7':571,'8':677,'9':763,':':760,';':759,'<':754,'=':494,'>':552,'?':537,'@':577,'A':692,
|
||||||
|
'B':786,'C':788,'D':788,'E':790,'F':793,'G':794,'H':816,'I':823,'J':789,'K':841,'L':823,'M':833,'N':816,'O':831,'P':923,'Q':744,'R':723,'S':749,'T':790,'U':792,'V':695,'W':776,
|
||||||
|
'X':768,'Y':792,'Z':759,'[':707,'\\':708,']':682,'^':701,'_':826,'`':815,'a':789,'b':789,'c':707,'d':687,'e':696,'f':689,'g':786,'h':787,'i':713,'j':791,'k':785,'l':791,'m':873,
|
||||||
|
'n':761,'o':762,'p':762,'q':759,'r':759,'s':892,'t':892,'u':788,'v':784,'w':438,'x':138,'y':277,'z':415,'{':392,'|':392,'}':668,'~':668,'\x7f':0,'\x80':390,'\x81':390,'\x82':317,'\x83':317,
|
||||||
|
'\x84':276,'\x85':276,'\x86':509,'\x87':509,'\x88':410,'\x89':410,'\x8a':234,'\x8b':234,'\x8c':334,'\x8d':334,'\x8e':0,'\x8f':0,'\x90':0,'\x91':0,'\x92':0,'\x93':0,'\x94':0,'\x95':0,'\x96':0,'\x97':0,'\x98':0,'\x99':0,
|
||||||
|
'\x9a':0,'\x9b':0,'\x9c':0,'\x9d':0,'\x9e':0,'\x9f':0,'\xa0':0,'\xa1':732,'\xa2':544,'\xa3':544,'\xa4':910,'\xa5':667,'\xa6':760,'\xa7':760,'\xa8':776,'\xa9':595,'\xaa':694,'\xab':626,'\xac':788,'\xad':788,'\xae':788,'\xaf':788,
|
||||||
|
'\xb0':788,'\xb1':788,'\xb2':788,'\xb3':788,'\xb4':788,'\xb5':788,'\xb6':788,'\xb7':788,'\xb8':788,'\xb9':788,'\xba':788,'\xbb':788,'\xbc':788,'\xbd':788,'\xbe':788,'\xbf':788,'\xc0':788,'\xc1':788,'\xc2':788,'\xc3':788,'\xc4':788,'\xc5':788,
|
||||||
|
'\xc6':788,'\xc7':788,'\xc8':788,'\xc9':788,'\xca':788,'\xcb':788,'\xcc':788,'\xcd':788,'\xce':788,'\xcf':788,'\xd0':788,'\xd1':788,'\xd2':788,'\xd3':788,'\xd4':894,'\xd5':838,'\xd6':1016,'\xd7':458,'\xd8':748,'\xd9':924,'\xda':748,'\xdb':918,
|
||||||
|
'\xdc':927,'\xdd':928,'\xde':928,'\xdf':834,'\xe0':873,'\xe1':828,'\xe2':924,'\xe3':924,'\xe4':917,'\xe5':930,'\xe6':931,'\xe7':463,'\xe8':883,'\xe9':836,'\xea':836,'\xeb':867,'\xec':867,'\xed':696,'\xee':696,'\xef':874,'\xf0':0,'\xf1':874,
|
||||||
|
'\xf2':760,'\xf3':946,'\xf4':771,'\xf5':865,'\xf6':771,'\xf7':888,'\xf8':967,'\xf9':888,'\xfa':831,'\xfb':873,'\xfc':927,'\xfd':970,'\xfe':918,'\xff':0}
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,402 @@
|
|||||||
|
# -*- coding: latin-1 -*-
|
||||||
|
|
||||||
|
"HTML Renderer for FPDF.py"
|
||||||
|
|
||||||
|
__author__ = "Mariano Reingart <reingart@gmail.com>"
|
||||||
|
__copyright__ = "Copyright (C) 2010 Mariano Reingart"
|
||||||
|
__license__ = "LGPL 3.0"
|
||||||
|
|
||||||
|
# Inspired by tuto5.py and several examples from fpdf.org, html2fpdf, etc.
|
||||||
|
|
||||||
|
from .fpdf import FPDF
|
||||||
|
from .py3k import PY3K, basestring, unicode, HTMLParser
|
||||||
|
|
||||||
|
DEBUG = False
|
||||||
|
|
||||||
|
def px2mm(px):
|
||||||
|
return int(px)*25.4/72.0
|
||||||
|
|
||||||
|
def hex2dec(color = "#000000"):
|
||||||
|
if color:
|
||||||
|
r = int(color[1:3], 16)
|
||||||
|
g = int(color[3:5], 16)
|
||||||
|
b = int(color[5:7], 16)
|
||||||
|
return r, g, b
|
||||||
|
|
||||||
|
class HTML2FPDF(HTMLParser):
|
||||||
|
"Render basic HTML to FPDF"
|
||||||
|
|
||||||
|
def __init__(self, pdf, image_map=None):
|
||||||
|
HTMLParser.__init__(self)
|
||||||
|
self.style = {}
|
||||||
|
self.pre = False
|
||||||
|
self.href = ''
|
||||||
|
self.align = ''
|
||||||
|
self.page_links = {}
|
||||||
|
self.font = None
|
||||||
|
self.font_stack = []
|
||||||
|
self.pdf = pdf
|
||||||
|
self.image_map = image_map or (lambda src: src)
|
||||||
|
self.r = self.g = self.b = 0
|
||||||
|
self.indent = 0
|
||||||
|
self.bullet = []
|
||||||
|
self.set_font("times", 12)
|
||||||
|
self.font_face = "times" # initialize font
|
||||||
|
self.color = 0 #initialize font color
|
||||||
|
self.table = None # table attributes
|
||||||
|
self.table_col_width = None # column (header) widths
|
||||||
|
self.table_col_index = None # current column index
|
||||||
|
self.td = None # cell attributes
|
||||||
|
self.th = False # header enabled
|
||||||
|
self.tr = None
|
||||||
|
self.theader = None # table header cells
|
||||||
|
self.tfooter = None # table footer cells
|
||||||
|
self.thead = None
|
||||||
|
self.tfoot = None
|
||||||
|
self.theader_out = self.tfooter_out = False
|
||||||
|
self.hsize = dict(h1=2, h2=1.5, h3=1.17, h4=1, h5=0.83, h6=0.67)
|
||||||
|
|
||||||
|
def width2mm(self, length):
|
||||||
|
if length[-1]=='%':
|
||||||
|
total = self.pdf.w - self.pdf.r_margin - self.pdf.l_margin
|
||||||
|
if self.table['width'][-1]=='%':
|
||||||
|
total *= int(self.table['width'][:-1])/100.0
|
||||||
|
return int(length[:-1]) * total / 101.0
|
||||||
|
else:
|
||||||
|
return int(length) / 6.0
|
||||||
|
|
||||||
|
def handle_data(self, txt):
|
||||||
|
if self.td is not None: # drawing a table?
|
||||||
|
if 'width' not in self.td and 'colspan' not in self.td:
|
||||||
|
try:
|
||||||
|
l = [self.table_col_width[self.table_col_index]]
|
||||||
|
except IndexError:
|
||||||
|
raise RuntimeError("Table column/cell width not specified, unable to continue")
|
||||||
|
elif 'colspan' in self.td:
|
||||||
|
i = self.table_col_index
|
||||||
|
colspan = int(self.td['colspan'])
|
||||||
|
l = self.table_col_width[i:i+colspan]
|
||||||
|
else:
|
||||||
|
l = [self.td.get('width','240')]
|
||||||
|
w = sum([self.width2mm(lenght) for lenght in l])
|
||||||
|
h = int(self.td.get('height', 0)) / 4 or self.h*1.30
|
||||||
|
self.table_h = h
|
||||||
|
border = int(self.table.get('border', 0))
|
||||||
|
if not self.th:
|
||||||
|
align = self.td.get('align', 'L')[0].upper()
|
||||||
|
border = border and 'LR'
|
||||||
|
else:
|
||||||
|
self.set_style('B',True)
|
||||||
|
border = border or 'B'
|
||||||
|
align = self.td.get('align', 'C')[0].upper()
|
||||||
|
bgcolor = hex2dec(self.td.get('bgcolor', self.tr.get('bgcolor', '')))
|
||||||
|
# parsing table header/footer (drawn later):
|
||||||
|
if self.thead is not None:
|
||||||
|
self.theader.append(((w,h,txt,border,0,align), bgcolor))
|
||||||
|
if self.tfoot is not None:
|
||||||
|
self.tfooter.append(((w,h,txt,border,0,align), bgcolor))
|
||||||
|
# check if reached end of page, add table footer and header:
|
||||||
|
height = h + (self.tfooter and self.tfooter[0][0][1] or 0)
|
||||||
|
if self.pdf.y+height>self.pdf.page_break_trigger and not self.th:
|
||||||
|
self.output_table_footer()
|
||||||
|
self.pdf.add_page()
|
||||||
|
self.theader_out = self.tfooter_out = False
|
||||||
|
if self.tfoot is None and self.thead is None:
|
||||||
|
if not self.theader_out:
|
||||||
|
self.output_table_header()
|
||||||
|
self.box_shadow(w, h, bgcolor)
|
||||||
|
if DEBUG: print("td cell", self.pdf.x, w, txt, "*")
|
||||||
|
self.pdf.cell(w,h,txt,border,0,align)
|
||||||
|
elif self.table is not None:
|
||||||
|
# ignore anything else than td inside a table
|
||||||
|
pass
|
||||||
|
elif self.align:
|
||||||
|
if DEBUG: print("cell", txt, "*")
|
||||||
|
self.pdf.cell(0,self.h,txt,0,1,self.align[0].upper(), self.href)
|
||||||
|
else:
|
||||||
|
txt = txt.replace("\n"," ")
|
||||||
|
if self.href:
|
||||||
|
self.put_link(self.href,txt)
|
||||||
|
else:
|
||||||
|
if DEBUG: print("write", txt, "*")
|
||||||
|
self.pdf.write(self.h,txt)
|
||||||
|
|
||||||
|
def box_shadow(self, w, h, bgcolor):
|
||||||
|
if DEBUG: print("box_shadow", w, h, bgcolor)
|
||||||
|
if bgcolor:
|
||||||
|
fill_color = self.pdf.fill_color
|
||||||
|
self.pdf.set_fill_color(*bgcolor)
|
||||||
|
self.pdf.rect(self.pdf.x, self.pdf.y, w, h, 'F')
|
||||||
|
self.pdf.fill_color = fill_color
|
||||||
|
|
||||||
|
def output_table_header(self):
|
||||||
|
if self.theader:
|
||||||
|
b = self.b
|
||||||
|
x = self.pdf.x
|
||||||
|
self.pdf.set_x(self.table_offset)
|
||||||
|
self.set_style('B',True)
|
||||||
|
for cell, bgcolor in self.theader:
|
||||||
|
self.box_shadow(cell[0], cell[1], bgcolor)
|
||||||
|
self.pdf.cell(*cell)
|
||||||
|
self.set_style('B',b)
|
||||||
|
self.pdf.ln(self.theader[0][0][1])
|
||||||
|
self.pdf.set_x(self.table_offset)
|
||||||
|
#self.pdf.set_x(x)
|
||||||
|
self.theader_out = True
|
||||||
|
|
||||||
|
def output_table_footer(self):
|
||||||
|
if self.tfooter:
|
||||||
|
x = self.pdf.x
|
||||||
|
self.pdf.set_x(self.table_offset)
|
||||||
|
#TODO: self.output_table_sep()
|
||||||
|
for cell, bgcolor in self.tfooter:
|
||||||
|
self.box_shadow(cell[0], cell[1], bgcolor)
|
||||||
|
self.pdf.cell(*cell)
|
||||||
|
self.pdf.ln(self.tfooter[0][0][1])
|
||||||
|
self.pdf.set_x(x)
|
||||||
|
if int(self.table.get('border', 0)):
|
||||||
|
self.output_table_sep()
|
||||||
|
self.tfooter_out = True
|
||||||
|
|
||||||
|
def output_table_sep(self):
|
||||||
|
self.pdf.set_x(self.table_offset)
|
||||||
|
x1 = self.pdf.x
|
||||||
|
y1 = self.pdf.y
|
||||||
|
w = sum([self.width2mm(lenght) for lenght in self.table_col_width])
|
||||||
|
self.pdf.line(x1,y1,x1+w,y1)
|
||||||
|
|
||||||
|
|
||||||
|
def handle_starttag(self, tag, attrs):
|
||||||
|
attrs = dict(attrs)
|
||||||
|
if DEBUG: print("STARTTAG", tag, attrs)
|
||||||
|
if tag=='b' or tag=='i' or tag=='u':
|
||||||
|
self.set_style(tag,1)
|
||||||
|
if tag=='a':
|
||||||
|
self.href=attrs['href']
|
||||||
|
if tag=='br':
|
||||||
|
self.pdf.ln(5)
|
||||||
|
if tag=='p':
|
||||||
|
self.pdf.ln(5)
|
||||||
|
if attrs:
|
||||||
|
if attrs: self.align = attrs.get('align')
|
||||||
|
if tag in self.hsize:
|
||||||
|
k = self.hsize[tag]
|
||||||
|
self.pdf.ln(5*k)
|
||||||
|
self.pdf.set_text_color(150,0,0)
|
||||||
|
self.pdf.set_font_size(12 * k)
|
||||||
|
if attrs: self.align = attrs.get('align')
|
||||||
|
if tag=='hr':
|
||||||
|
self.put_line()
|
||||||
|
if tag=='pre':
|
||||||
|
self.pdf.set_font('Courier','',11)
|
||||||
|
self.pdf.set_font_size(11)
|
||||||
|
self.set_style('B',False)
|
||||||
|
self.set_style('I',False)
|
||||||
|
self.pre = True
|
||||||
|
if tag=='blockquote':
|
||||||
|
self.set_text_color(100,0,45)
|
||||||
|
self.pdf.ln(3)
|
||||||
|
if tag=='ul':
|
||||||
|
self.indent+=1
|
||||||
|
self.bullet.append('\x95')
|
||||||
|
if tag=='ol':
|
||||||
|
self.indent+=1
|
||||||
|
self.bullet.append(0)
|
||||||
|
if tag=='li':
|
||||||
|
self.pdf.ln(self.h+2)
|
||||||
|
self.pdf.set_text_color(190,0,0)
|
||||||
|
bullet = self.bullet[self.indent-1]
|
||||||
|
if not isinstance(bullet, basestring):
|
||||||
|
bullet += 1
|
||||||
|
self.bullet[self.indent-1] = bullet
|
||||||
|
bullet = "%s. " % bullet
|
||||||
|
self.pdf.write(self.h,'%s%s ' % (' '*5*self.indent, bullet))
|
||||||
|
self.set_text_color()
|
||||||
|
if tag=='font':
|
||||||
|
# save previous font state:
|
||||||
|
self.font_stack.append((self.font_face, self.font_size, self.color))
|
||||||
|
if 'color' in attrs:
|
||||||
|
self.color = hex2dec(attrs['color'])
|
||||||
|
self.set_text_color(*color)
|
||||||
|
self.color = color
|
||||||
|
if 'face' in attrs:
|
||||||
|
face = attrs.get('face').lower()
|
||||||
|
try:
|
||||||
|
self.pdf.set_font(face)
|
||||||
|
self.font_face = face
|
||||||
|
except RuntimeError:
|
||||||
|
pass # font not found, ignore
|
||||||
|
if 'size' in attrs:
|
||||||
|
size = int(attrs.get('size'))
|
||||||
|
self.pdf.set_font(self.font_face, size=int(size))
|
||||||
|
self.font_size = size
|
||||||
|
if tag=='table':
|
||||||
|
self.table = dict([(k.lower(), v) for k,v in attrs.items()])
|
||||||
|
if not 'width' in self.table:
|
||||||
|
self.table['width'] = '100%'
|
||||||
|
if self.table['width'][-1]=='%':
|
||||||
|
w = self.pdf.w - self.pdf.r_margin - self.pdf.l_margin
|
||||||
|
w *= int(self.table['width'][:-1])/100.0
|
||||||
|
self.table_offset = (self.pdf.w-w)/2.0
|
||||||
|
self.table_col_width = []
|
||||||
|
self.theader_out = self.tfooter_out = False
|
||||||
|
self.theader = []
|
||||||
|
self.tfooter = []
|
||||||
|
self.thead = None
|
||||||
|
self.tfoot = None
|
||||||
|
self.table_h = 0
|
||||||
|
self.pdf.ln()
|
||||||
|
if tag=='tr':
|
||||||
|
self.tr = dict([(k.lower(), v) for k,v in attrs.items()])
|
||||||
|
self.table_col_index = 0
|
||||||
|
self.pdf.set_x(self.table_offset)
|
||||||
|
if tag=='td':
|
||||||
|
self.td = dict([(k.lower(), v) for k,v in attrs.items()])
|
||||||
|
if tag=='th':
|
||||||
|
self.td = dict([(k.lower(), v) for k,v in attrs.items()])
|
||||||
|
self.th = True
|
||||||
|
if 'width' in self.td:
|
||||||
|
self.table_col_width.append(self.td['width'])
|
||||||
|
if tag=='thead':
|
||||||
|
self.thead = {}
|
||||||
|
if tag=='tfoot':
|
||||||
|
self.tfoot = {}
|
||||||
|
if tag=='img':
|
||||||
|
if 'src' in attrs:
|
||||||
|
x = self.pdf.get_x()
|
||||||
|
y = self.pdf.get_y()
|
||||||
|
w = px2mm(attrs.get('width', 0))
|
||||||
|
h = px2mm(attrs.get('height',0))
|
||||||
|
if self.align and self.align[0].upper() == 'C':
|
||||||
|
x = (self.pdf.w-x)/2.0 - w/2.0
|
||||||
|
self.pdf.image(self.image_map(attrs['src']),
|
||||||
|
x, y, w, h, link=self.href)
|
||||||
|
self.pdf.set_x(x+w)
|
||||||
|
self.pdf.set_y(y+h)
|
||||||
|
if tag=='b' or tag=='i' or tag=='u':
|
||||||
|
self.set_style(tag, True)
|
||||||
|
if tag=='center':
|
||||||
|
self.align = 'Center'
|
||||||
|
|
||||||
|
def handle_endtag(self, tag):
|
||||||
|
#Closing tag
|
||||||
|
if DEBUG: print("ENDTAG", tag)
|
||||||
|
if tag=='h1' or tag=='h2' or tag=='h3' or tag=='h4':
|
||||||
|
self.pdf.ln(6)
|
||||||
|
self.set_font()
|
||||||
|
self.set_style()
|
||||||
|
self.align = None
|
||||||
|
if tag=='pre':
|
||||||
|
self.pdf.set_font(self.font or 'Times','',12)
|
||||||
|
self.pdf.set_font_size(12)
|
||||||
|
self.pre=False
|
||||||
|
if tag=='blockquote':
|
||||||
|
self.set_text_color(0,0,0)
|
||||||
|
self.pdf.ln(3)
|
||||||
|
if tag=='strong':
|
||||||
|
tag='b'
|
||||||
|
if tag=='em':
|
||||||
|
tag='i'
|
||||||
|
if tag=='b' or tag=='i' or tag=='u':
|
||||||
|
self.set_style(tag, False)
|
||||||
|
if tag=='a':
|
||||||
|
self.href=''
|
||||||
|
if tag=='p':
|
||||||
|
self.align=''
|
||||||
|
if tag in ('ul', 'ol'):
|
||||||
|
self.indent-=1
|
||||||
|
self.bullet.pop()
|
||||||
|
if tag=='table':
|
||||||
|
if not self.tfooter_out:
|
||||||
|
self.output_table_footer()
|
||||||
|
self.table = None
|
||||||
|
self.th = False
|
||||||
|
self.theader = None
|
||||||
|
self.tfooter = None
|
||||||
|
self.pdf.ln()
|
||||||
|
if tag=='thead':
|
||||||
|
self.thead = None
|
||||||
|
if tag=='tfoot':
|
||||||
|
self.tfoot = None
|
||||||
|
if tag=='tbody':
|
||||||
|
# draw a line separator between table bodies
|
||||||
|
self.pdf.set_x(self.table_offset)
|
||||||
|
self.output_table_sep()
|
||||||
|
if tag=='tr':
|
||||||
|
h = self.table_h
|
||||||
|
if self.tfoot is None:
|
||||||
|
self.pdf.ln(h)
|
||||||
|
self.tr = None
|
||||||
|
if tag=='td' or tag=='th':
|
||||||
|
if self.th:
|
||||||
|
if DEBUG: print("revert style")
|
||||||
|
self.set_style('B', False) # revert style
|
||||||
|
self.table_col_index += int(self.td.get('colspan','1'))
|
||||||
|
self.td = None
|
||||||
|
self.th = False
|
||||||
|
if tag=='font':
|
||||||
|
# recover last font state
|
||||||
|
face, size, color = self.font_stack.pop()
|
||||||
|
if face:
|
||||||
|
self.pdf.set_text_color(0,0,0)
|
||||||
|
self.color = None
|
||||||
|
self.set_font(face, size)
|
||||||
|
self.font = None
|
||||||
|
if tag=='center':
|
||||||
|
self.align = None
|
||||||
|
|
||||||
|
def set_font(self, face=None, size=None):
|
||||||
|
if face:
|
||||||
|
self.font_face = face
|
||||||
|
if size:
|
||||||
|
self.font_size = size
|
||||||
|
self.h = size / 72.0*25.4
|
||||||
|
if DEBUG: print("H", self.h)
|
||||||
|
self.pdf.set_font(self.font_face or 'times','',12)
|
||||||
|
self.pdf.set_font_size(self.font_size or 12)
|
||||||
|
self.set_style('u', False)
|
||||||
|
self.set_style('b', False)
|
||||||
|
self.set_style('i', False)
|
||||||
|
self.set_text_color()
|
||||||
|
|
||||||
|
def set_style(self, tag=None, enable=None):
|
||||||
|
#Modify style and select corresponding font
|
||||||
|
if tag:
|
||||||
|
t = self.style.get(tag.lower())
|
||||||
|
self.style[tag.lower()] = enable
|
||||||
|
style=''
|
||||||
|
for s in ('b','i','u'):
|
||||||
|
if self.style.get(s):
|
||||||
|
style+=s
|
||||||
|
if DEBUG: print("SET_FONT_STYLE", style)
|
||||||
|
self.pdf.set_font('',style)
|
||||||
|
|
||||||
|
def set_text_color(self, r=None, g=0, b=0):
|
||||||
|
if r is None:
|
||||||
|
self.pdf.set_text_color(self.r,self.g,self.b)
|
||||||
|
else:
|
||||||
|
self.pdf.set_text_color(r, g, b)
|
||||||
|
self.r = r
|
||||||
|
self.g = g
|
||||||
|
self.b = b
|
||||||
|
|
||||||
|
def put_link(self, url, txt):
|
||||||
|
#Put a hyperlink
|
||||||
|
self.set_text_color(0,0,255)
|
||||||
|
self.set_style('u', True)
|
||||||
|
self.pdf.write(5,txt,url)
|
||||||
|
self.set_style('u', False)
|
||||||
|
self.set_text_color(0)
|
||||||
|
|
||||||
|
def put_line(self):
|
||||||
|
self.pdf.ln(2)
|
||||||
|
self.pdf.line(self.pdf.get_x(),self.pdf.get_y(),self.pdf.get_x()+187,self.pdf.get_y())
|
||||||
|
self.pdf.ln(3)
|
||||||
|
|
||||||
|
class HTMLMixin(object):
|
||||||
|
def write_html(self, text, image_map=None):
|
||||||
|
"Parse HTML and convert it to PDF"
|
||||||
|
h2p = HTML2FPDF(self, image_map)
|
||||||
|
text = h2p.unescape(text) # To deal with HTML entities
|
||||||
|
h2p.feed(text)
|
||||||
|
|
@ -0,0 +1,54 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
# -*- coding: latin-1 -*-
|
||||||
|
|
||||||
|
from .py3k import PY3K, basestring, unicode
|
||||||
|
|
||||||
|
# fpdf php helpers:
|
||||||
|
|
||||||
|
def substr(s, start, length=-1):
|
||||||
|
if length < 0:
|
||||||
|
length=len(s)-start
|
||||||
|
return s[start:start+length]
|
||||||
|
|
||||||
|
def sprintf(fmt, *args): return fmt % args
|
||||||
|
|
||||||
|
def print_r(array):
|
||||||
|
if not isinstance(array, dict):
|
||||||
|
array = dict([(k, k) for k in array])
|
||||||
|
for k, v in array.items():
|
||||||
|
print("[%s] => %s " % (k, v))
|
||||||
|
|
||||||
|
def UTF8ToUTF16BE(instr, setbom=True):
|
||||||
|
"Converts UTF-8 strings to UTF16-BE."
|
||||||
|
outstr = "".encode()
|
||||||
|
if (setbom):
|
||||||
|
outstr += "\xFE\xFF".encode("latin1")
|
||||||
|
if not isinstance(instr, unicode):
|
||||||
|
instr = instr.decode('UTF-8')
|
||||||
|
outstr += instr.encode('UTF-16BE')
|
||||||
|
# convert bytes back to fake unicode string until PEP461-like is implemented
|
||||||
|
if PY3K:
|
||||||
|
outstr = outstr.decode("latin1")
|
||||||
|
return outstr
|
||||||
|
|
||||||
|
def UTF8StringToArray(instr):
|
||||||
|
"Converts UTF-8 strings to codepoints array"
|
||||||
|
return [ord(c) for c in instr]
|
||||||
|
|
||||||
|
# ttfints php helpers:
|
||||||
|
|
||||||
|
def die(msg):
|
||||||
|
raise RuntimeError(msg)
|
||||||
|
|
||||||
|
def str_repeat(s, count):
|
||||||
|
return s * count
|
||||||
|
|
||||||
|
def str_pad(s, pad_length=0, pad_char= " ", pad_type= +1 ):
|
||||||
|
if pad_type<0: # pad left
|
||||||
|
return s.rjust(pad_length, pad_char)
|
||||||
|
elif pad_type>0: # pad right
|
||||||
|
return s.ljust(pad_length, pad_char)
|
||||||
|
else: # pad both
|
||||||
|
return s.center(pad_length, pad_char)
|
||||||
|
|
||||||
|
strlen = count = lambda s: len(s)
|
@ -0,0 +1,75 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
"Special module to handle differences between Python 2 and 3 versions"
|
||||||
|
|
||||||
|
import sys
|
||||||
|
|
||||||
|
PY3K = sys.version_info >= (3, 0)
|
||||||
|
|
||||||
|
try:
|
||||||
|
import cPickle as pickle
|
||||||
|
except ImportError:
|
||||||
|
import pickle
|
||||||
|
|
||||||
|
try:
|
||||||
|
from urllib import urlopen
|
||||||
|
except ImportError:
|
||||||
|
from urllib.request import urlopen
|
||||||
|
|
||||||
|
try:
|
||||||
|
from hashlib import md5
|
||||||
|
except ImportError:
|
||||||
|
try:
|
||||||
|
from md5 import md5
|
||||||
|
except ImportError:
|
||||||
|
md5 = None
|
||||||
|
def hashpath(fn):
|
||||||
|
h = md5()
|
||||||
|
if PY3K:
|
||||||
|
h.update(fn.encode("UTF-8"))
|
||||||
|
else:
|
||||||
|
h.update(fn)
|
||||||
|
return h.hexdigest()
|
||||||
|
|
||||||
|
# Check if PIL is available (tries importing both pypi version and corrected or manually installed versions).
|
||||||
|
# Necessary for JPEG and GIF support.
|
||||||
|
# TODO: Pillow support
|
||||||
|
try:
|
||||||
|
from PIL import Image
|
||||||
|
except ImportError:
|
||||||
|
try:
|
||||||
|
import Image
|
||||||
|
except ImportError:
|
||||||
|
Image = None
|
||||||
|
|
||||||
|
try:
|
||||||
|
from HTMLParser import HTMLParser
|
||||||
|
except ImportError:
|
||||||
|
from html.parser import HTMLParser
|
||||||
|
|
||||||
|
if PY3K:
|
||||||
|
basestring = str
|
||||||
|
unicode = str
|
||||||
|
ord = lambda x: x
|
||||||
|
else:
|
||||||
|
basestring = basestring
|
||||||
|
unicode = unicode
|
||||||
|
ord = ord
|
||||||
|
|
||||||
|
# shortcut to bytes conversion (b prefix)
|
||||||
|
def b(s):
|
||||||
|
if isinstance(s, basestring):
|
||||||
|
return s.encode("latin1")
|
||||||
|
elif isinstance(s, int):
|
||||||
|
if PY3K:
|
||||||
|
return bytes([s]) # http://bugs.python.org/issue4588
|
||||||
|
else:
|
||||||
|
return chr(s)
|
||||||
|
|
||||||
|
def exception():
|
||||||
|
"Return the current the exception instance currently being handled"
|
||||||
|
# this is needed to support Python 2.5 that lacks "as" syntax
|
||||||
|
return sys.exc_info()[1]
|
||||||
|
|
||||||
|
|
@ -0,0 +1,226 @@
|
|||||||
|
# -*- coding: iso-8859-1 -*-
|
||||||
|
|
||||||
|
"PDF Template Helper for FPDF.py"
|
||||||
|
|
||||||
|
__author__ = "Mariano Reingart <reingart@gmail.com>"
|
||||||
|
__copyright__ = "Copyright (C) 2010 Mariano Reingart"
|
||||||
|
__license__ = "LGPL 3.0"
|
||||||
|
|
||||||
|
import sys,os,csv
|
||||||
|
from .fpdf import FPDF
|
||||||
|
from .py3k import PY3K, basestring, unicode
|
||||||
|
|
||||||
|
def rgb(col):
|
||||||
|
return (col // 65536), (col // 256 % 256), (col% 256)
|
||||||
|
|
||||||
|
class Template:
|
||||||
|
def __init__(self, infile=None, elements=None, format='A4', orientation='portrait',
|
||||||
|
title='', author='', subject='', creator='', keywords=''):
|
||||||
|
if elements:
|
||||||
|
self.load_elements(elements)
|
||||||
|
self.handlers = {'T': self.text, 'L': self.line, 'I': self.image,
|
||||||
|
'B': self.rect, 'BC': self.barcode, 'W': self.write, }
|
||||||
|
self.texts = {}
|
||||||
|
pdf = self.pdf = FPDF(format=format,orientation=orientation, unit="mm")
|
||||||
|
pdf.set_title(title)
|
||||||
|
pdf.set_author(author)
|
||||||
|
pdf.set_creator(creator)
|
||||||
|
pdf.set_subject(subject)
|
||||||
|
pdf.set_keywords(keywords)
|
||||||
|
|
||||||
|
def load_elements(self, elements):
|
||||||
|
"Initialize the internal element structures"
|
||||||
|
self.pg_no = 0
|
||||||
|
self.elements = elements
|
||||||
|
self.keys = [v['name'].lower() for v in self.elements]
|
||||||
|
|
||||||
|
def parse_csv(self, infile, delimiter=",", decimal_sep="."):
|
||||||
|
"Parse template format csv file and create elements dict"
|
||||||
|
keys = ('name','type','x1','y1','x2','y2','font','size',
|
||||||
|
'bold','italic','underline','foreground','background',
|
||||||
|
'align','text','priority', 'multiline')
|
||||||
|
self.elements = []
|
||||||
|
self.pg_no = 0
|
||||||
|
if not PY3K:
|
||||||
|
f = open(infile, 'rb')
|
||||||
|
else:
|
||||||
|
f = open(infile)
|
||||||
|
for row in csv.reader(f, delimiter=delimiter):
|
||||||
|
kargs = {}
|
||||||
|
for i,v in enumerate(row):
|
||||||
|
if not v.startswith("'") and decimal_sep!=".":
|
||||||
|
v = v.replace(decimal_sep,".")
|
||||||
|
else:
|
||||||
|
v = v
|
||||||
|
if v=='':
|
||||||
|
v = None
|
||||||
|
else:
|
||||||
|
v = eval(v.strip())
|
||||||
|
kargs[keys[i]] = v
|
||||||
|
self.elements.append(kargs)
|
||||||
|
self.keys = [v['name'].lower() for v in self.elements]
|
||||||
|
|
||||||
|
def add_page(self):
|
||||||
|
self.pg_no += 1
|
||||||
|
self.texts[self.pg_no] = {}
|
||||||
|
|
||||||
|
def __setitem__(self, name, value):
|
||||||
|
if name.lower() in self.keys:
|
||||||
|
if not PY3K and isinstance(value, unicode):
|
||||||
|
value = value.encode("latin1","ignore")
|
||||||
|
elif value is None:
|
||||||
|
value = ""
|
||||||
|
else:
|
||||||
|
value = str(value)
|
||||||
|
self.texts[self.pg_no][name.lower()] = value
|
||||||
|
|
||||||
|
# setitem shortcut (may be further extended)
|
||||||
|
set = __setitem__
|
||||||
|
|
||||||
|
def has_key(self, name):
|
||||||
|
return name.lower() in self.keys
|
||||||
|
|
||||||
|
def __getitem__(self, name):
|
||||||
|
if name in self.keys:
|
||||||
|
key = name.lower()
|
||||||
|
if key in self.texts:
|
||||||
|
# text for this page:
|
||||||
|
return self.texts[self.pg_no][key]
|
||||||
|
else:
|
||||||
|
# find first element for default text:
|
||||||
|
elements = [element for element in self.elements
|
||||||
|
if element['name'].lower() == key]
|
||||||
|
if elements:
|
||||||
|
return elements[0]['text']
|
||||||
|
|
||||||
|
def split_multicell(self, text, element_name):
|
||||||
|
"Divide (\n) a string using a given element width"
|
||||||
|
pdf = self.pdf
|
||||||
|
element = [element for element in self.elements
|
||||||
|
if element['name'].lower() == element_name.lower()][0]
|
||||||
|
style = ""
|
||||||
|
if element['bold']: style += "B"
|
||||||
|
if element['italic']: style += "I"
|
||||||
|
if element['underline']: style += "U"
|
||||||
|
pdf.set_font(element['font'],style,element['size'])
|
||||||
|
align = {'L':'L','R':'R','I':'L','D':'R','C':'C','':''}.get(element['align']) # D/I in spanish
|
||||||
|
if isinstance(text, unicode) and not PY3K:
|
||||||
|
text = text.encode("latin1","ignore")
|
||||||
|
else:
|
||||||
|
text = str(text)
|
||||||
|
return pdf.multi_cell(w=element['x2']-element['x1'],
|
||||||
|
h=element['y2']-element['y1'],
|
||||||
|
txt=text,align=align,split_only=True)
|
||||||
|
|
||||||
|
def render(self, outfile, dest="F"):
|
||||||
|
pdf = self.pdf
|
||||||
|
for pg in range(1, self.pg_no+1):
|
||||||
|
pdf.add_page()
|
||||||
|
pdf.set_font('Arial','B',16)
|
||||||
|
pdf.set_auto_page_break(False,margin=0)
|
||||||
|
|
||||||
|
for element in sorted(self.elements,key=lambda x: x['priority']):
|
||||||
|
#print "dib",element['type'], element['name'], element['x1'], element['y1'], element['x2'], element['y2']
|
||||||
|
element = element.copy()
|
||||||
|
element['text'] = self.texts[pg].get(element['name'].lower(), element['text'])
|
||||||
|
if 'rotate' in element:
|
||||||
|
pdf.rotate(element['rotate'], element['x1'], element['y1'])
|
||||||
|
self.handlers[element['type'].upper()](pdf, **element)
|
||||||
|
if 'rotate' in element:
|
||||||
|
pdf.rotate(0)
|
||||||
|
|
||||||
|
if dest:
|
||||||
|
return pdf.output(outfile, dest)
|
||||||
|
|
||||||
|
def text(self, pdf, x1=0, y1=0, x2=0, y2=0, text='', font="arial", size=10,
|
||||||
|
bold=False, italic=False, underline=False, align="",
|
||||||
|
foreground=0, backgroud=65535, multiline=None,
|
||||||
|
*args, **kwargs):
|
||||||
|
if text:
|
||||||
|
if pdf.text_color!=rgb(foreground):
|
||||||
|
pdf.set_text_color(*rgb(foreground))
|
||||||
|
if pdf.fill_color!=rgb(backgroud):
|
||||||
|
pdf.set_fill_color(*rgb(backgroud))
|
||||||
|
|
||||||
|
font = font.strip().lower()
|
||||||
|
if font == 'arial black':
|
||||||
|
font = 'arial'
|
||||||
|
style = ""
|
||||||
|
for tag in 'B', 'I', 'U':
|
||||||
|
if (text.startswith("<%s>" % tag) and text.endswith("</%s>" %tag)):
|
||||||
|
text = text[3:-4]
|
||||||
|
style += tag
|
||||||
|
if bold: style += "B"
|
||||||
|
if italic: style += "I"
|
||||||
|
if underline: style += "U"
|
||||||
|
align = {'L':'L','R':'R','I':'L','D':'R','C':'C','':''}.get(align) # D/I in spanish
|
||||||
|
pdf.set_font(font,style,size)
|
||||||
|
##m_k = 72 / 2.54
|
||||||
|
##h = (size/m_k)
|
||||||
|
pdf.set_xy(x1,y1)
|
||||||
|
if multiline is None:
|
||||||
|
# multiline==None: write without wrapping/trimming (default)
|
||||||
|
pdf.cell(w=x2-x1,h=y2-y1,txt=text,border=0,ln=0,align=align)
|
||||||
|
elif multiline:
|
||||||
|
# multiline==True: automatic word - warp
|
||||||
|
pdf.multi_cell(w=x2-x1,h=y2-y1,txt=text,border=0,align=align)
|
||||||
|
else:
|
||||||
|
# multiline==False: trim to fit exactly the space defined
|
||||||
|
text = pdf.multi_cell(w=x2-x1, h=y2-y1,
|
||||||
|
txt=text, align=align, split_only=True)[0]
|
||||||
|
print("trimming: *%s*" % text)
|
||||||
|
pdf.cell(w=x2-x1,h=y2-y1,txt=text,border=0,ln=0,align=align)
|
||||||
|
|
||||||
|
#pdf.Text(x=x1,y=y1,txt=text)
|
||||||
|
|
||||||
|
def line(self, pdf, x1=0, y1=0, x2=0, y2=0, size=0, foreground=0, *args, **kwargs):
|
||||||
|
if pdf.draw_color!=rgb(foreground):
|
||||||
|
#print "SetDrawColor", hex(foreground)
|
||||||
|
pdf.set_draw_color(*rgb(foreground))
|
||||||
|
#print "SetLineWidth", size
|
||||||
|
pdf.set_line_width(size)
|
||||||
|
pdf.line(x1, y1, x2, y2)
|
||||||
|
|
||||||
|
def rect(self, pdf, x1=0, y1=0, x2=0, y2=0, size=0, foreground=0, backgroud=65535, *args, **kwargs):
|
||||||
|
if pdf.draw_color!=rgb(foreground):
|
||||||
|
pdf.set_draw_color(*rgb(foreground))
|
||||||
|
if pdf.fill_color!=rgb(backgroud):
|
||||||
|
pdf.set_fill_color(*rgb(backgroud))
|
||||||
|
pdf.set_line_width(size)
|
||||||
|
pdf.rect(x1, y1, x2-x1, y2-y1)
|
||||||
|
|
||||||
|
def image(self, pdf, x1=0, y1=0, x2=0, y2=0, text='', *args,**kwargs):
|
||||||
|
if text:
|
||||||
|
pdf.image(text,x1,y1,w=x2-x1,h=y2-y1,type='',link='')
|
||||||
|
|
||||||
|
def barcode(self, pdf, x1=0, y1=0, x2=0, y2=0, text='', font="arial", size=1,
|
||||||
|
foreground=0, *args, **kwargs):
|
||||||
|
if pdf.draw_color!=rgb(foreground):
|
||||||
|
pdf.set_draw_color(*rgb(foreground))
|
||||||
|
font = font.lower().strip()
|
||||||
|
if font == 'interleaved 2of5 nt':
|
||||||
|
pdf.interleaved2of5(text,x1,y1,w=size,h=y2-y1)
|
||||||
|
|
||||||
|
# Added by Derek Schwalenberg Schwalenberg1013@gmail.com to allow (url) links in templates (using write method) 2014-02-22
|
||||||
|
def write(self, pdf, x1=0, y1=0, x2=0, y2=0, text='', font="arial", size=1,
|
||||||
|
bold=False, italic=False, underline=False, align="", link='http://example.com',
|
||||||
|
foreground=0, *args, **kwargs):
|
||||||
|
if pdf.text_color!=rgb(foreground):
|
||||||
|
pdf.set_text_color(*rgb(foreground))
|
||||||
|
font = font.strip().lower()
|
||||||
|
if font == 'arial black':
|
||||||
|
font = 'arial'
|
||||||
|
style = ""
|
||||||
|
for tag in 'B', 'I', 'U':
|
||||||
|
if (text.startswith("<%s>" % tag) and text.endswith("</%s>" %tag)):
|
||||||
|
text = text[3:-4]
|
||||||
|
style += tag
|
||||||
|
if bold: style += "B"
|
||||||
|
if italic: style += "I"
|
||||||
|
if underline: style += "U"
|
||||||
|
align = {'L':'L','R':'R','I':'L','D':'R','C':'C','':''}.get(align) # D/I in spanish
|
||||||
|
pdf.set_font(font,style,size)
|
||||||
|
##m_k = 72 / 2.54
|
||||||
|
##h = (size/m_k)
|
||||||
|
pdf.set_xy(x1,y1)
|
||||||
|
pdf.write(5,text,link)
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,37 @@
|
|||||||
|
"""Jinja is a template engine written in pure Python. It provides a
|
||||||
|
non-XML syntax that supports inline expressions and an optional
|
||||||
|
sandboxed environment.
|
||||||
|
"""
|
||||||
|
from .bccache import BytecodeCache as BytecodeCache
|
||||||
|
from .bccache import FileSystemBytecodeCache as FileSystemBytecodeCache
|
||||||
|
from .bccache import MemcachedBytecodeCache as MemcachedBytecodeCache
|
||||||
|
from .environment import Environment as Environment
|
||||||
|
from .environment import Template as Template
|
||||||
|
from .exceptions import TemplateAssertionError as TemplateAssertionError
|
||||||
|
from .exceptions import TemplateError as TemplateError
|
||||||
|
from .exceptions import TemplateNotFound as TemplateNotFound
|
||||||
|
from .exceptions import TemplateRuntimeError as TemplateRuntimeError
|
||||||
|
from .exceptions import TemplatesNotFound as TemplatesNotFound
|
||||||
|
from .exceptions import TemplateSyntaxError as TemplateSyntaxError
|
||||||
|
from .exceptions import UndefinedError as UndefinedError
|
||||||
|
from .loaders import BaseLoader as BaseLoader
|
||||||
|
from .loaders import ChoiceLoader as ChoiceLoader
|
||||||
|
from .loaders import DictLoader as DictLoader
|
||||||
|
from .loaders import FileSystemLoader as FileSystemLoader
|
||||||
|
from .loaders import FunctionLoader as FunctionLoader
|
||||||
|
from .loaders import ModuleLoader as ModuleLoader
|
||||||
|
from .loaders import PackageLoader as PackageLoader
|
||||||
|
from .loaders import PrefixLoader as PrefixLoader
|
||||||
|
from .runtime import ChainableUndefined as ChainableUndefined
|
||||||
|
from .runtime import DebugUndefined as DebugUndefined
|
||||||
|
from .runtime import make_logging_undefined as make_logging_undefined
|
||||||
|
from .runtime import StrictUndefined as StrictUndefined
|
||||||
|
from .runtime import Undefined as Undefined
|
||||||
|
from .utils import clear_caches as clear_caches
|
||||||
|
from .utils import is_undefined as is_undefined
|
||||||
|
from .utils import pass_context as pass_context
|
||||||
|
from .utils import pass_environment as pass_environment
|
||||||
|
from .utils import pass_eval_context as pass_eval_context
|
||||||
|
from .utils import select_autoescape as select_autoescape
|
||||||
|
|
||||||
|
__version__ = "3.1.3"
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1,84 @@
|
|||||||
|
import inspect
|
||||||
|
import typing as t
|
||||||
|
from functools import WRAPPER_ASSIGNMENTS
|
||||||
|
from functools import wraps
|
||||||
|
|
||||||
|
from .utils import _PassArg
|
||||||
|
from .utils import pass_eval_context
|
||||||
|
|
||||||
|
V = t.TypeVar("V")
|
||||||
|
|
||||||
|
|
||||||
|
def async_variant(normal_func): # type: ignore
|
||||||
|
def decorator(async_func): # type: ignore
|
||||||
|
pass_arg = _PassArg.from_obj(normal_func)
|
||||||
|
need_eval_context = pass_arg is None
|
||||||
|
|
||||||
|
if pass_arg is _PassArg.environment:
|
||||||
|
|
||||||
|
def is_async(args: t.Any) -> bool:
|
||||||
|
return t.cast(bool, args[0].is_async)
|
||||||
|
|
||||||
|
else:
|
||||||
|
|
||||||
|
def is_async(args: t.Any) -> bool:
|
||||||
|
return t.cast(bool, args[0].environment.is_async)
|
||||||
|
|
||||||
|
# Take the doc and annotations from the sync function, but the
|
||||||
|
# name from the async function. Pallets-Sphinx-Themes
|
||||||
|
# build_function_directive expects __wrapped__ to point to the
|
||||||
|
# sync function.
|
||||||
|
async_func_attrs = ("__module__", "__name__", "__qualname__")
|
||||||
|
normal_func_attrs = tuple(set(WRAPPER_ASSIGNMENTS).difference(async_func_attrs))
|
||||||
|
|
||||||
|
@wraps(normal_func, assigned=normal_func_attrs)
|
||||||
|
@wraps(async_func, assigned=async_func_attrs, updated=())
|
||||||
|
def wrapper(*args, **kwargs): # type: ignore
|
||||||
|
b = is_async(args)
|
||||||
|
|
||||||
|
if need_eval_context:
|
||||||
|
args = args[1:]
|
||||||
|
|
||||||
|
if b:
|
||||||
|
return async_func(*args, **kwargs)
|
||||||
|
|
||||||
|
return normal_func(*args, **kwargs)
|
||||||
|
|
||||||
|
if need_eval_context:
|
||||||
|
wrapper = pass_eval_context(wrapper)
|
||||||
|
|
||||||
|
wrapper.jinja_async_variant = True
|
||||||
|
return wrapper
|
||||||
|
|
||||||
|
return decorator
|
||||||
|
|
||||||
|
|
||||||
|
_common_primitives = {int, float, bool, str, list, dict, tuple, type(None)}
|
||||||
|
|
||||||
|
|
||||||
|
async def auto_await(value: t.Union[t.Awaitable["V"], "V"]) -> "V":
|
||||||
|
# Avoid a costly call to isawaitable
|
||||||
|
if type(value) in _common_primitives:
|
||||||
|
return t.cast("V", value)
|
||||||
|
|
||||||
|
if inspect.isawaitable(value):
|
||||||
|
return await t.cast("t.Awaitable[V]", value)
|
||||||
|
|
||||||
|
return t.cast("V", value)
|
||||||
|
|
||||||
|
|
||||||
|
async def auto_aiter(
|
||||||
|
iterable: "t.Union[t.AsyncIterable[V], t.Iterable[V]]",
|
||||||
|
) -> "t.AsyncIterator[V]":
|
||||||
|
if hasattr(iterable, "__aiter__"):
|
||||||
|
async for item in t.cast("t.AsyncIterable[V]", iterable):
|
||||||
|
yield item
|
||||||
|
else:
|
||||||
|
for item in iterable:
|
||||||
|
yield item
|
||||||
|
|
||||||
|
|
||||||
|
async def auto_to_list(
|
||||||
|
value: "t.Union[t.AsyncIterable[V], t.Iterable[V]]",
|
||||||
|
) -> t.List["V"]:
|
||||||
|
return [x async for x in auto_aiter(value)]
|
@ -0,0 +1,406 @@
|
|||||||
|
"""The optional bytecode cache system. This is useful if you have very
|
||||||
|
complex template situations and the compilation of all those templates
|
||||||
|
slows down your application too much.
|
||||||
|
|
||||||
|
Situations where this is useful are often forking web applications that
|
||||||
|
are initialized on the first request.
|
||||||
|
"""
|
||||||
|
import errno
|
||||||
|
import fnmatch
|
||||||
|
import marshal
|
||||||
|
import os
|
||||||
|
import pickle
|
||||||
|
import stat
|
||||||
|
import sys
|
||||||
|
import tempfile
|
||||||
|
import typing as t
|
||||||
|
from hashlib import sha1
|
||||||
|
from io import BytesIO
|
||||||
|
from types import CodeType
|
||||||
|
|
||||||
|
if t.TYPE_CHECKING:
|
||||||
|
import typing_extensions as te
|
||||||
|
from .environment import Environment
|
||||||
|
|
||||||
|
class _MemcachedClient(te.Protocol):
|
||||||
|
def get(self, key: str) -> bytes:
|
||||||
|
...
|
||||||
|
|
||||||
|
def set(self, key: str, value: bytes, timeout: t.Optional[int] = None) -> None:
|
||||||
|
...
|
||||||
|
|
||||||
|
|
||||||
|
bc_version = 5
|
||||||
|
# Magic bytes to identify Jinja bytecode cache files. Contains the
|
||||||
|
# Python major and minor version to avoid loading incompatible bytecode
|
||||||
|
# if a project upgrades its Python version.
|
||||||
|
bc_magic = (
|
||||||
|
b"j2"
|
||||||
|
+ pickle.dumps(bc_version, 2)
|
||||||
|
+ pickle.dumps((sys.version_info[0] << 24) | sys.version_info[1], 2)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class Bucket:
|
||||||
|
"""Buckets are used to store the bytecode for one template. It's created
|
||||||
|
and initialized by the bytecode cache and passed to the loading functions.
|
||||||
|
|
||||||
|
The buckets get an internal checksum from the cache assigned and use this
|
||||||
|
to automatically reject outdated cache material. Individual bytecode
|
||||||
|
cache subclasses don't have to care about cache invalidation.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, environment: "Environment", key: str, checksum: str) -> None:
|
||||||
|
self.environment = environment
|
||||||
|
self.key = key
|
||||||
|
self.checksum = checksum
|
||||||
|
self.reset()
|
||||||
|
|
||||||
|
def reset(self) -> None:
|
||||||
|
"""Resets the bucket (unloads the bytecode)."""
|
||||||
|
self.code: t.Optional[CodeType] = None
|
||||||
|
|
||||||
|
def load_bytecode(self, f: t.BinaryIO) -> None:
|
||||||
|
"""Loads bytecode from a file or file like object."""
|
||||||
|
# make sure the magic header is correct
|
||||||
|
magic = f.read(len(bc_magic))
|
||||||
|
if magic != bc_magic:
|
||||||
|
self.reset()
|
||||||
|
return
|
||||||
|
# the source code of the file changed, we need to reload
|
||||||
|
checksum = pickle.load(f)
|
||||||
|
if self.checksum != checksum:
|
||||||
|
self.reset()
|
||||||
|
return
|
||||||
|
# if marshal_load fails then we need to reload
|
||||||
|
try:
|
||||||
|
self.code = marshal.load(f)
|
||||||
|
except (EOFError, ValueError, TypeError):
|
||||||
|
self.reset()
|
||||||
|
return
|
||||||
|
|
||||||
|
def write_bytecode(self, f: t.IO[bytes]) -> None:
|
||||||
|
"""Dump the bytecode into the file or file like object passed."""
|
||||||
|
if self.code is None:
|
||||||
|
raise TypeError("can't write empty bucket")
|
||||||
|
f.write(bc_magic)
|
||||||
|
pickle.dump(self.checksum, f, 2)
|
||||||
|
marshal.dump(self.code, f)
|
||||||
|
|
||||||
|
def bytecode_from_string(self, string: bytes) -> None:
|
||||||
|
"""Load bytecode from bytes."""
|
||||||
|
self.load_bytecode(BytesIO(string))
|
||||||
|
|
||||||
|
def bytecode_to_string(self) -> bytes:
|
||||||
|
"""Return the bytecode as bytes."""
|
||||||
|
out = BytesIO()
|
||||||
|
self.write_bytecode(out)
|
||||||
|
return out.getvalue()
|
||||||
|
|
||||||
|
|
||||||
|
class BytecodeCache:
|
||||||
|
"""To implement your own bytecode cache you have to subclass this class
|
||||||
|
and override :meth:`load_bytecode` and :meth:`dump_bytecode`. Both of
|
||||||
|
these methods are passed a :class:`~jinja2.bccache.Bucket`.
|
||||||
|
|
||||||
|
A very basic bytecode cache that saves the bytecode on the file system::
|
||||||
|
|
||||||
|
from os import path
|
||||||
|
|
||||||
|
class MyCache(BytecodeCache):
|
||||||
|
|
||||||
|
def __init__(self, directory):
|
||||||
|
self.directory = directory
|
||||||
|
|
||||||
|
def load_bytecode(self, bucket):
|
||||||
|
filename = path.join(self.directory, bucket.key)
|
||||||
|
if path.exists(filename):
|
||||||
|
with open(filename, 'rb') as f:
|
||||||
|
bucket.load_bytecode(f)
|
||||||
|
|
||||||
|
def dump_bytecode(self, bucket):
|
||||||
|
filename = path.join(self.directory, bucket.key)
|
||||||
|
with open(filename, 'wb') as f:
|
||||||
|
bucket.write_bytecode(f)
|
||||||
|
|
||||||
|
A more advanced version of a filesystem based bytecode cache is part of
|
||||||
|
Jinja.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def load_bytecode(self, bucket: Bucket) -> None:
|
||||||
|
"""Subclasses have to override this method to load bytecode into a
|
||||||
|
bucket. If they are not able to find code in the cache for the
|
||||||
|
bucket, it must not do anything.
|
||||||
|
"""
|
||||||
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
def dump_bytecode(self, bucket: Bucket) -> None:
|
||||||
|
"""Subclasses have to override this method to write the bytecode
|
||||||
|
from a bucket back to the cache. If it unable to do so it must not
|
||||||
|
fail silently but raise an exception.
|
||||||
|
"""
|
||||||
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
def clear(self) -> None:
|
||||||
|
"""Clears the cache. This method is not used by Jinja but should be
|
||||||
|
implemented to allow applications to clear the bytecode cache used
|
||||||
|
by a particular environment.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def get_cache_key(
|
||||||
|
self, name: str, filename: t.Optional[t.Union[str]] = None
|
||||||
|
) -> str:
|
||||||
|
"""Returns the unique hash key for this template name."""
|
||||||
|
hash = sha1(name.encode("utf-8"))
|
||||||
|
|
||||||
|
if filename is not None:
|
||||||
|
hash.update(f"|{filename}".encode())
|
||||||
|
|
||||||
|
return hash.hexdigest()
|
||||||
|
|
||||||
|
def get_source_checksum(self, source: str) -> str:
|
||||||
|
"""Returns a checksum for the source."""
|
||||||
|
return sha1(source.encode("utf-8")).hexdigest()
|
||||||
|
|
||||||
|
def get_bucket(
|
||||||
|
self,
|
||||||
|
environment: "Environment",
|
||||||
|
name: str,
|
||||||
|
filename: t.Optional[str],
|
||||||
|
source: str,
|
||||||
|
) -> Bucket:
|
||||||
|
"""Return a cache bucket for the given template. All arguments are
|
||||||
|
mandatory but filename may be `None`.
|
||||||
|
"""
|
||||||
|
key = self.get_cache_key(name, filename)
|
||||||
|
checksum = self.get_source_checksum(source)
|
||||||
|
bucket = Bucket(environment, key, checksum)
|
||||||
|
self.load_bytecode(bucket)
|
||||||
|
return bucket
|
||||||
|
|
||||||
|
def set_bucket(self, bucket: Bucket) -> None:
|
||||||
|
"""Put the bucket into the cache."""
|
||||||
|
self.dump_bytecode(bucket)
|
||||||
|
|
||||||
|
|
||||||
|
class FileSystemBytecodeCache(BytecodeCache):
|
||||||
|
"""A bytecode cache that stores bytecode on the filesystem. It accepts
|
||||||
|
two arguments: The directory where the cache items are stored and a
|
||||||
|
pattern string that is used to build the filename.
|
||||||
|
|
||||||
|
If no directory is specified a default cache directory is selected. On
|
||||||
|
Windows the user's temp directory is used, on UNIX systems a directory
|
||||||
|
is created for the user in the system temp directory.
|
||||||
|
|
||||||
|
The pattern can be used to have multiple separate caches operate on the
|
||||||
|
same directory. The default pattern is ``'__jinja2_%s.cache'``. ``%s``
|
||||||
|
is replaced with the cache key.
|
||||||
|
|
||||||
|
>>> bcc = FileSystemBytecodeCache('/tmp/jinja_cache', '%s.cache')
|
||||||
|
|
||||||
|
This bytecode cache supports clearing of the cache using the clear method.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self, directory: t.Optional[str] = None, pattern: str = "__jinja2_%s.cache"
|
||||||
|
) -> None:
|
||||||
|
if directory is None:
|
||||||
|
directory = self._get_default_cache_dir()
|
||||||
|
self.directory = directory
|
||||||
|
self.pattern = pattern
|
||||||
|
|
||||||
|
def _get_default_cache_dir(self) -> str:
|
||||||
|
def _unsafe_dir() -> "te.NoReturn":
|
||||||
|
raise RuntimeError(
|
||||||
|
"Cannot determine safe temp directory. You "
|
||||||
|
"need to explicitly provide one."
|
||||||
|
)
|
||||||
|
|
||||||
|
tmpdir = tempfile.gettempdir()
|
||||||
|
|
||||||
|
# On windows the temporary directory is used specific unless
|
||||||
|
# explicitly forced otherwise. We can just use that.
|
||||||
|
if os.name == "nt":
|
||||||
|
return tmpdir
|
||||||
|
if not hasattr(os, "getuid"):
|
||||||
|
_unsafe_dir()
|
||||||
|
|
||||||
|
dirname = f"_jinja2-cache-{os.getuid()}"
|
||||||
|
actual_dir = os.path.join(tmpdir, dirname)
|
||||||
|
|
||||||
|
try:
|
||||||
|
os.mkdir(actual_dir, stat.S_IRWXU)
|
||||||
|
except OSError as e:
|
||||||
|
if e.errno != errno.EEXIST:
|
||||||
|
raise
|
||||||
|
try:
|
||||||
|
os.chmod(actual_dir, stat.S_IRWXU)
|
||||||
|
actual_dir_stat = os.lstat(actual_dir)
|
||||||
|
if (
|
||||||
|
actual_dir_stat.st_uid != os.getuid()
|
||||||
|
or not stat.S_ISDIR(actual_dir_stat.st_mode)
|
||||||
|
or stat.S_IMODE(actual_dir_stat.st_mode) != stat.S_IRWXU
|
||||||
|
):
|
||||||
|
_unsafe_dir()
|
||||||
|
except OSError as e:
|
||||||
|
if e.errno != errno.EEXIST:
|
||||||
|
raise
|
||||||
|
|
||||||
|
actual_dir_stat = os.lstat(actual_dir)
|
||||||
|
if (
|
||||||
|
actual_dir_stat.st_uid != os.getuid()
|
||||||
|
or not stat.S_ISDIR(actual_dir_stat.st_mode)
|
||||||
|
or stat.S_IMODE(actual_dir_stat.st_mode) != stat.S_IRWXU
|
||||||
|
):
|
||||||
|
_unsafe_dir()
|
||||||
|
|
||||||
|
return actual_dir
|
||||||
|
|
||||||
|
def _get_cache_filename(self, bucket: Bucket) -> str:
|
||||||
|
return os.path.join(self.directory, self.pattern % (bucket.key,))
|
||||||
|
|
||||||
|
def load_bytecode(self, bucket: Bucket) -> None:
|
||||||
|
filename = self._get_cache_filename(bucket)
|
||||||
|
|
||||||
|
# Don't test for existence before opening the file, since the
|
||||||
|
# file could disappear after the test before the open.
|
||||||
|
try:
|
||||||
|
f = open(filename, "rb")
|
||||||
|
except (FileNotFoundError, IsADirectoryError, PermissionError):
|
||||||
|
# PermissionError can occur on Windows when an operation is
|
||||||
|
# in progress, such as calling clear().
|
||||||
|
return
|
||||||
|
|
||||||
|
with f:
|
||||||
|
bucket.load_bytecode(f)
|
||||||
|
|
||||||
|
def dump_bytecode(self, bucket: Bucket) -> None:
|
||||||
|
# Write to a temporary file, then rename to the real name after
|
||||||
|
# writing. This avoids another process reading the file before
|
||||||
|
# it is fully written.
|
||||||
|
name = self._get_cache_filename(bucket)
|
||||||
|
f = tempfile.NamedTemporaryFile(
|
||||||
|
mode="wb",
|
||||||
|
dir=os.path.dirname(name),
|
||||||
|
prefix=os.path.basename(name),
|
||||||
|
suffix=".tmp",
|
||||||
|
delete=False,
|
||||||
|
)
|
||||||
|
|
||||||
|
def remove_silent() -> None:
|
||||||
|
try:
|
||||||
|
os.remove(f.name)
|
||||||
|
except OSError:
|
||||||
|
# Another process may have called clear(). On Windows,
|
||||||
|
# another program may be holding the file open.
|
||||||
|
pass
|
||||||
|
|
||||||
|
try:
|
||||||
|
with f:
|
||||||
|
bucket.write_bytecode(f)
|
||||||
|
except BaseException:
|
||||||
|
remove_silent()
|
||||||
|
raise
|
||||||
|
|
||||||
|
try:
|
||||||
|
os.replace(f.name, name)
|
||||||
|
except OSError:
|
||||||
|
# Another process may have called clear(). On Windows,
|
||||||
|
# another program may be holding the file open.
|
||||||
|
remove_silent()
|
||||||
|
except BaseException:
|
||||||
|
remove_silent()
|
||||||
|
raise
|
||||||
|
|
||||||
|
def clear(self) -> None:
|
||||||
|
# imported lazily here because google app-engine doesn't support
|
||||||
|
# write access on the file system and the function does not exist
|
||||||
|
# normally.
|
||||||
|
from os import remove
|
||||||
|
|
||||||
|
files = fnmatch.filter(os.listdir(self.directory), self.pattern % ("*",))
|
||||||
|
for filename in files:
|
||||||
|
try:
|
||||||
|
remove(os.path.join(self.directory, filename))
|
||||||
|
except OSError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class MemcachedBytecodeCache(BytecodeCache):
|
||||||
|
"""This class implements a bytecode cache that uses a memcache cache for
|
||||||
|
storing the information. It does not enforce a specific memcache library
|
||||||
|
(tummy's memcache or cmemcache) but will accept any class that provides
|
||||||
|
the minimal interface required.
|
||||||
|
|
||||||
|
Libraries compatible with this class:
|
||||||
|
|
||||||
|
- `cachelib <https://github.com/pallets/cachelib>`_
|
||||||
|
- `python-memcached <https://pypi.org/project/python-memcached/>`_
|
||||||
|
|
||||||
|
(Unfortunately the django cache interface is not compatible because it
|
||||||
|
does not support storing binary data, only text. You can however pass
|
||||||
|
the underlying cache client to the bytecode cache which is available
|
||||||
|
as `django.core.cache.cache._client`.)
|
||||||
|
|
||||||
|
The minimal interface for the client passed to the constructor is this:
|
||||||
|
|
||||||
|
.. class:: MinimalClientInterface
|
||||||
|
|
||||||
|
.. method:: set(key, value[, timeout])
|
||||||
|
|
||||||
|
Stores the bytecode in the cache. `value` is a string and
|
||||||
|
`timeout` the timeout of the key. If timeout is not provided
|
||||||
|
a default timeout or no timeout should be assumed, if it's
|
||||||
|
provided it's an integer with the number of seconds the cache
|
||||||
|
item should exist.
|
||||||
|
|
||||||
|
.. method:: get(key)
|
||||||
|
|
||||||
|
Returns the value for the cache key. If the item does not
|
||||||
|
exist in the cache the return value must be `None`.
|
||||||
|
|
||||||
|
The other arguments to the constructor are the prefix for all keys that
|
||||||
|
is added before the actual cache key and the timeout for the bytecode in
|
||||||
|
the cache system. We recommend a high (or no) timeout.
|
||||||
|
|
||||||
|
This bytecode cache does not support clearing of used items in the cache.
|
||||||
|
The clear method is a no-operation function.
|
||||||
|
|
||||||
|
.. versionadded:: 2.7
|
||||||
|
Added support for ignoring memcache errors through the
|
||||||
|
`ignore_memcache_errors` parameter.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
client: "_MemcachedClient",
|
||||||
|
prefix: str = "jinja2/bytecode/",
|
||||||
|
timeout: t.Optional[int] = None,
|
||||||
|
ignore_memcache_errors: bool = True,
|
||||||
|
):
|
||||||
|
self.client = client
|
||||||
|
self.prefix = prefix
|
||||||
|
self.timeout = timeout
|
||||||
|
self.ignore_memcache_errors = ignore_memcache_errors
|
||||||
|
|
||||||
|
def load_bytecode(self, bucket: Bucket) -> None:
|
||||||
|
try:
|
||||||
|
code = self.client.get(self.prefix + bucket.key)
|
||||||
|
except Exception:
|
||||||
|
if not self.ignore_memcache_errors:
|
||||||
|
raise
|
||||||
|
else:
|
||||||
|
bucket.bytecode_from_string(code)
|
||||||
|
|
||||||
|
def dump_bytecode(self, bucket: Bucket) -> None:
|
||||||
|
key = self.prefix + bucket.key
|
||||||
|
value = bucket.bytecode_to_string()
|
||||||
|
|
||||||
|
try:
|
||||||
|
if self.timeout is not None:
|
||||||
|
self.client.set(key, value, self.timeout)
|
||||||
|
else:
|
||||||
|
self.client.set(key, value)
|
||||||
|
except Exception:
|
||||||
|
if not self.ignore_memcache_errors:
|
||||||
|
raise
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,20 @@
|
|||||||
|
#: list of lorem ipsum words used by the lipsum() helper function
|
||||||
|
LOREM_IPSUM_WORDS = """\
|
||||||
|
a ac accumsan ad adipiscing aenean aliquam aliquet amet ante aptent arcu at
|
||||||
|
auctor augue bibendum blandit class commodo condimentum congue consectetuer
|
||||||
|
consequat conubia convallis cras cubilia cum curabitur curae cursus dapibus
|
||||||
|
diam dictum dictumst dignissim dis dolor donec dui duis egestas eget eleifend
|
||||||
|
elementum elit enim erat eros est et etiam eu euismod facilisi facilisis fames
|
||||||
|
faucibus felis fermentum feugiat fringilla fusce gravida habitant habitasse hac
|
||||||
|
hendrerit hymenaeos iaculis id imperdiet in inceptos integer interdum ipsum
|
||||||
|
justo lacinia lacus laoreet lectus leo libero ligula litora lobortis lorem
|
||||||
|
luctus maecenas magna magnis malesuada massa mattis mauris metus mi molestie
|
||||||
|
mollis montes morbi mus nam nascetur natoque nec neque netus nibh nisi nisl non
|
||||||
|
nonummy nostra nulla nullam nunc odio orci ornare parturient pede pellentesque
|
||||||
|
penatibus per pharetra phasellus placerat platea porta porttitor posuere
|
||||||
|
potenti praesent pretium primis proin pulvinar purus quam quis quisque rhoncus
|
||||||
|
ridiculus risus rutrum sagittis sapien scelerisque sed sem semper senectus sit
|
||||||
|
sociis sociosqu sodales sollicitudin suscipit suspendisse taciti tellus tempor
|
||||||
|
tempus tincidunt torquent tortor tristique turpis ullamcorper ultrices
|
||||||
|
ultricies urna ut varius vehicula vel velit venenatis vestibulum vitae vivamus
|
||||||
|
viverra volutpat vulputate"""
|
@ -0,0 +1,191 @@
|
|||||||
|
import sys
|
||||||
|
import typing as t
|
||||||
|
from types import CodeType
|
||||||
|
from types import TracebackType
|
||||||
|
|
||||||
|
from .exceptions import TemplateSyntaxError
|
||||||
|
from .utils import internal_code
|
||||||
|
from .utils import missing
|
||||||
|
|
||||||
|
if t.TYPE_CHECKING:
|
||||||
|
from .runtime import Context
|
||||||
|
|
||||||
|
|
||||||
|
def rewrite_traceback_stack(source: t.Optional[str] = None) -> BaseException:
|
||||||
|
"""Rewrite the current exception to replace any tracebacks from
|
||||||
|
within compiled template code with tracebacks that look like they
|
||||||
|
came from the template source.
|
||||||
|
|
||||||
|
This must be called within an ``except`` block.
|
||||||
|
|
||||||
|
:param source: For ``TemplateSyntaxError``, the original source if
|
||||||
|
known.
|
||||||
|
:return: The original exception with the rewritten traceback.
|
||||||
|
"""
|
||||||
|
_, exc_value, tb = sys.exc_info()
|
||||||
|
exc_value = t.cast(BaseException, exc_value)
|
||||||
|
tb = t.cast(TracebackType, tb)
|
||||||
|
|
||||||
|
if isinstance(exc_value, TemplateSyntaxError) and not exc_value.translated:
|
||||||
|
exc_value.translated = True
|
||||||
|
exc_value.source = source
|
||||||
|
# Remove the old traceback, otherwise the frames from the
|
||||||
|
# compiler still show up.
|
||||||
|
exc_value.with_traceback(None)
|
||||||
|
# Outside of runtime, so the frame isn't executing template
|
||||||
|
# code, but it still needs to point at the template.
|
||||||
|
tb = fake_traceback(
|
||||||
|
exc_value, None, exc_value.filename or "<unknown>", exc_value.lineno
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
# Skip the frame for the render function.
|
||||||
|
tb = tb.tb_next
|
||||||
|
|
||||||
|
stack = []
|
||||||
|
|
||||||
|
# Build the stack of traceback object, replacing any in template
|
||||||
|
# code with the source file and line information.
|
||||||
|
while tb is not None:
|
||||||
|
# Skip frames decorated with @internalcode. These are internal
|
||||||
|
# calls that aren't useful in template debugging output.
|
||||||
|
if tb.tb_frame.f_code in internal_code:
|
||||||
|
tb = tb.tb_next
|
||||||
|
continue
|
||||||
|
|
||||||
|
template = tb.tb_frame.f_globals.get("__jinja_template__")
|
||||||
|
|
||||||
|
if template is not None:
|
||||||
|
lineno = template.get_corresponding_lineno(tb.tb_lineno)
|
||||||
|
fake_tb = fake_traceback(exc_value, tb, template.filename, lineno)
|
||||||
|
stack.append(fake_tb)
|
||||||
|
else:
|
||||||
|
stack.append(tb)
|
||||||
|
|
||||||
|
tb = tb.tb_next
|
||||||
|
|
||||||
|
tb_next = None
|
||||||
|
|
||||||
|
# Assign tb_next in reverse to avoid circular references.
|
||||||
|
for tb in reversed(stack):
|
||||||
|
tb.tb_next = tb_next
|
||||||
|
tb_next = tb
|
||||||
|
|
||||||
|
return exc_value.with_traceback(tb_next)
|
||||||
|
|
||||||
|
|
||||||
|
def fake_traceback( # type: ignore
|
||||||
|
exc_value: BaseException, tb: t.Optional[TracebackType], filename: str, lineno: int
|
||||||
|
) -> TracebackType:
|
||||||
|
"""Produce a new traceback object that looks like it came from the
|
||||||
|
template source instead of the compiled code. The filename, line
|
||||||
|
number, and location name will point to the template, and the local
|
||||||
|
variables will be the current template context.
|
||||||
|
|
||||||
|
:param exc_value: The original exception to be re-raised to create
|
||||||
|
the new traceback.
|
||||||
|
:param tb: The original traceback to get the local variables and
|
||||||
|
code info from.
|
||||||
|
:param filename: The template filename.
|
||||||
|
:param lineno: The line number in the template source.
|
||||||
|
"""
|
||||||
|
if tb is not None:
|
||||||
|
# Replace the real locals with the context that would be
|
||||||
|
# available at that point in the template.
|
||||||
|
locals = get_template_locals(tb.tb_frame.f_locals)
|
||||||
|
locals.pop("__jinja_exception__", None)
|
||||||
|
else:
|
||||||
|
locals = {}
|
||||||
|
|
||||||
|
globals = {
|
||||||
|
"__name__": filename,
|
||||||
|
"__file__": filename,
|
||||||
|
"__jinja_exception__": exc_value,
|
||||||
|
}
|
||||||
|
# Raise an exception at the correct line number.
|
||||||
|
code: CodeType = compile(
|
||||||
|
"\n" * (lineno - 1) + "raise __jinja_exception__", filename, "exec"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Build a new code object that points to the template file and
|
||||||
|
# replaces the location with a block name.
|
||||||
|
location = "template"
|
||||||
|
|
||||||
|
if tb is not None:
|
||||||
|
function = tb.tb_frame.f_code.co_name
|
||||||
|
|
||||||
|
if function == "root":
|
||||||
|
location = "top-level template code"
|
||||||
|
elif function.startswith("block_"):
|
||||||
|
location = f"block {function[6:]!r}"
|
||||||
|
|
||||||
|
if sys.version_info >= (3, 8):
|
||||||
|
code = code.replace(co_name=location)
|
||||||
|
else:
|
||||||
|
code = CodeType(
|
||||||
|
code.co_argcount,
|
||||||
|
code.co_kwonlyargcount,
|
||||||
|
code.co_nlocals,
|
||||||
|
code.co_stacksize,
|
||||||
|
code.co_flags,
|
||||||
|
code.co_code,
|
||||||
|
code.co_consts,
|
||||||
|
code.co_names,
|
||||||
|
code.co_varnames,
|
||||||
|
code.co_filename,
|
||||||
|
location,
|
||||||
|
code.co_firstlineno,
|
||||||
|
code.co_lnotab,
|
||||||
|
code.co_freevars,
|
||||||
|
code.co_cellvars,
|
||||||
|
)
|
||||||
|
|
||||||
|
# Execute the new code, which is guaranteed to raise, and return
|
||||||
|
# the new traceback without this frame.
|
||||||
|
try:
|
||||||
|
exec(code, globals, locals)
|
||||||
|
except BaseException:
|
||||||
|
return sys.exc_info()[2].tb_next # type: ignore
|
||||||
|
|
||||||
|
|
||||||
|
def get_template_locals(real_locals: t.Mapping[str, t.Any]) -> t.Dict[str, t.Any]:
|
||||||
|
"""Based on the runtime locals, get the context that would be
|
||||||
|
available at that point in the template.
|
||||||
|
"""
|
||||||
|
# Start with the current template context.
|
||||||
|
ctx: "t.Optional[Context]" = real_locals.get("context")
|
||||||
|
|
||||||
|
if ctx is not None:
|
||||||
|
data: t.Dict[str, t.Any] = ctx.get_all().copy()
|
||||||
|
else:
|
||||||
|
data = {}
|
||||||
|
|
||||||
|
# Might be in a derived context that only sets local variables
|
||||||
|
# rather than pushing a context. Local variables follow the scheme
|
||||||
|
# l_depth_name. Find the highest-depth local that has a value for
|
||||||
|
# each name.
|
||||||
|
local_overrides: t.Dict[str, t.Tuple[int, t.Any]] = {}
|
||||||
|
|
||||||
|
for name, value in real_locals.items():
|
||||||
|
if not name.startswith("l_") or value is missing:
|
||||||
|
# Not a template variable, or no longer relevant.
|
||||||
|
continue
|
||||||
|
|
||||||
|
try:
|
||||||
|
_, depth_str, name = name.split("_", 2)
|
||||||
|
depth = int(depth_str)
|
||||||
|
except ValueError:
|
||||||
|
continue
|
||||||
|
|
||||||
|
cur_depth = local_overrides.get(name, (-1,))[0]
|
||||||
|
|
||||||
|
if cur_depth < depth:
|
||||||
|
local_overrides[name] = (depth, value)
|
||||||
|
|
||||||
|
# Modify the context with any derived context.
|
||||||
|
for name, (_, value) in local_overrides.items():
|
||||||
|
if value is missing:
|
||||||
|
data.pop(name, None)
|
||||||
|
else:
|
||||||
|
data[name] = value
|
||||||
|
|
||||||
|
return data
|
@ -0,0 +1,48 @@
|
|||||||
|
import typing as t
|
||||||
|
|
||||||
|
from .filters import FILTERS as DEFAULT_FILTERS # noqa: F401
|
||||||
|
from .tests import TESTS as DEFAULT_TESTS # noqa: F401
|
||||||
|
from .utils import Cycler
|
||||||
|
from .utils import generate_lorem_ipsum
|
||||||
|
from .utils import Joiner
|
||||||
|
from .utils import Namespace
|
||||||
|
|
||||||
|
if t.TYPE_CHECKING:
|
||||||
|
import typing_extensions as te
|
||||||
|
|
||||||
|
# defaults for the parser / lexer
|
||||||
|
BLOCK_START_STRING = "{%"
|
||||||
|
BLOCK_END_STRING = "%}"
|
||||||
|
VARIABLE_START_STRING = "{{"
|
||||||
|
VARIABLE_END_STRING = "}}"
|
||||||
|
COMMENT_START_STRING = "{#"
|
||||||
|
COMMENT_END_STRING = "#}"
|
||||||
|
LINE_STATEMENT_PREFIX: t.Optional[str] = None
|
||||||
|
LINE_COMMENT_PREFIX: t.Optional[str] = None
|
||||||
|
TRIM_BLOCKS = False
|
||||||
|
LSTRIP_BLOCKS = False
|
||||||
|
NEWLINE_SEQUENCE: "te.Literal['\\n', '\\r\\n', '\\r']" = "\n"
|
||||||
|
KEEP_TRAILING_NEWLINE = False
|
||||||
|
|
||||||
|
# default filters, tests and namespace
|
||||||
|
|
||||||
|
DEFAULT_NAMESPACE = {
|
||||||
|
"range": range,
|
||||||
|
"dict": dict,
|
||||||
|
"lipsum": generate_lorem_ipsum,
|
||||||
|
"cycler": Cycler,
|
||||||
|
"joiner": Joiner,
|
||||||
|
"namespace": Namespace,
|
||||||
|
}
|
||||||
|
|
||||||
|
# default policies
|
||||||
|
DEFAULT_POLICIES: t.Dict[str, t.Any] = {
|
||||||
|
"compiler.ascii_str": True,
|
||||||
|
"urlize.rel": "noopener",
|
||||||
|
"urlize.target": None,
|
||||||
|
"urlize.extra_schemes": None,
|
||||||
|
"truncate.leeway": 5,
|
||||||
|
"json.dumps_function": None,
|
||||||
|
"json.dumps_kwargs": {"sort_keys": True},
|
||||||
|
"ext.i18n.trimmed": False,
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,166 @@
|
|||||||
|
import typing as t
|
||||||
|
|
||||||
|
if t.TYPE_CHECKING:
|
||||||
|
from .runtime import Undefined
|
||||||
|
|
||||||
|
|
||||||
|
class TemplateError(Exception):
|
||||||
|
"""Baseclass for all template errors."""
|
||||||
|
|
||||||
|
def __init__(self, message: t.Optional[str] = None) -> None:
|
||||||
|
super().__init__(message)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def message(self) -> t.Optional[str]:
|
||||||
|
return self.args[0] if self.args else None
|
||||||
|
|
||||||
|
|
||||||
|
class TemplateNotFound(IOError, LookupError, TemplateError):
|
||||||
|
"""Raised if a template does not exist.
|
||||||
|
|
||||||
|
.. versionchanged:: 2.11
|
||||||
|
If the given name is :class:`Undefined` and no message was
|
||||||
|
provided, an :exc:`UndefinedError` is raised.
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Silence the Python warning about message being deprecated since
|
||||||
|
# it's not valid here.
|
||||||
|
message: t.Optional[str] = None
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
name: t.Optional[t.Union[str, "Undefined"]],
|
||||||
|
message: t.Optional[str] = None,
|
||||||
|
) -> None:
|
||||||
|
IOError.__init__(self, name)
|
||||||
|
|
||||||
|
if message is None:
|
||||||
|
from .runtime import Undefined
|
||||||
|
|
||||||
|
if isinstance(name, Undefined):
|
||||||
|
name._fail_with_undefined_error()
|
||||||
|
|
||||||
|
message = name
|
||||||
|
|
||||||
|
self.message = message
|
||||||
|
self.name = name
|
||||||
|
self.templates = [name]
|
||||||
|
|
||||||
|
def __str__(self) -> str:
|
||||||
|
return str(self.message)
|
||||||
|
|
||||||
|
|
||||||
|
class TemplatesNotFound(TemplateNotFound):
|
||||||
|
"""Like :class:`TemplateNotFound` but raised if multiple templates
|
||||||
|
are selected. This is a subclass of :class:`TemplateNotFound`
|
||||||
|
exception, so just catching the base exception will catch both.
|
||||||
|
|
||||||
|
.. versionchanged:: 2.11
|
||||||
|
If a name in the list of names is :class:`Undefined`, a message
|
||||||
|
about it being undefined is shown rather than the empty string.
|
||||||
|
|
||||||
|
.. versionadded:: 2.2
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
names: t.Sequence[t.Union[str, "Undefined"]] = (),
|
||||||
|
message: t.Optional[str] = None,
|
||||||
|
) -> None:
|
||||||
|
if message is None:
|
||||||
|
from .runtime import Undefined
|
||||||
|
|
||||||
|
parts = []
|
||||||
|
|
||||||
|
for name in names:
|
||||||
|
if isinstance(name, Undefined):
|
||||||
|
parts.append(name._undefined_message)
|
||||||
|
else:
|
||||||
|
parts.append(name)
|
||||||
|
|
||||||
|
parts_str = ", ".join(map(str, parts))
|
||||||
|
message = f"none of the templates given were found: {parts_str}"
|
||||||
|
|
||||||
|
super().__init__(names[-1] if names else None, message)
|
||||||
|
self.templates = list(names)
|
||||||
|
|
||||||
|
|
||||||
|
class TemplateSyntaxError(TemplateError):
|
||||||
|
"""Raised to tell the user that there is a problem with the template."""
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
message: str,
|
||||||
|
lineno: int,
|
||||||
|
name: t.Optional[str] = None,
|
||||||
|
filename: t.Optional[str] = None,
|
||||||
|
) -> None:
|
||||||
|
super().__init__(message)
|
||||||
|
self.lineno = lineno
|
||||||
|
self.name = name
|
||||||
|
self.filename = filename
|
||||||
|
self.source: t.Optional[str] = None
|
||||||
|
|
||||||
|
# this is set to True if the debug.translate_syntax_error
|
||||||
|
# function translated the syntax error into a new traceback
|
||||||
|
self.translated = False
|
||||||
|
|
||||||
|
def __str__(self) -> str:
|
||||||
|
# for translated errors we only return the message
|
||||||
|
if self.translated:
|
||||||
|
return t.cast(str, self.message)
|
||||||
|
|
||||||
|
# otherwise attach some stuff
|
||||||
|
location = f"line {self.lineno}"
|
||||||
|
name = self.filename or self.name
|
||||||
|
if name:
|
||||||
|
location = f'File "{name}", {location}'
|
||||||
|
lines = [t.cast(str, self.message), " " + location]
|
||||||
|
|
||||||
|
# if the source is set, add the line to the output
|
||||||
|
if self.source is not None:
|
||||||
|
try:
|
||||||
|
line = self.source.splitlines()[self.lineno - 1]
|
||||||
|
except IndexError:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
lines.append(" " + line.strip())
|
||||||
|
|
||||||
|
return "\n".join(lines)
|
||||||
|
|
||||||
|
def __reduce__(self): # type: ignore
|
||||||
|
# https://bugs.python.org/issue1692335 Exceptions that take
|
||||||
|
# multiple required arguments have problems with pickling.
|
||||||
|
# Without this, raises TypeError: __init__() missing 1 required
|
||||||
|
# positional argument: 'lineno'
|
||||||
|
return self.__class__, (self.message, self.lineno, self.name, self.filename)
|
||||||
|
|
||||||
|
|
||||||
|
class TemplateAssertionError(TemplateSyntaxError):
|
||||||
|
"""Like a template syntax error, but covers cases where something in the
|
||||||
|
template caused an error at compile time that wasn't necessarily caused
|
||||||
|
by a syntax error. However it's a direct subclass of
|
||||||
|
:exc:`TemplateSyntaxError` and has the same attributes.
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
class TemplateRuntimeError(TemplateError):
|
||||||
|
"""A generic runtime error in the template engine. Under some situations
|
||||||
|
Jinja may raise this exception.
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
class UndefinedError(TemplateRuntimeError):
|
||||||
|
"""Raised if a template tries to operate on :class:`Undefined`."""
|
||||||
|
|
||||||
|
|
||||||
|
class SecurityError(TemplateRuntimeError):
|
||||||
|
"""Raised if a template tries to do something insecure if the
|
||||||
|
sandbox is enabled.
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
class FilterArgumentError(TemplateRuntimeError):
|
||||||
|
"""This error is raised if a filter was called with inappropriate
|
||||||
|
arguments
|
||||||
|
"""
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue