new_feature

This commit is contained in:
Wenxin Tian 2023-12-04 12:01:38 -05:00
parent 8bce025c15
commit 34578f015c
4231 changed files with 861226 additions and 52 deletions

241
ihatemoney/bin/Activate.ps1 Normal file
View file

@ -0,0 +1,241 @@
<#
.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 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 virutal 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
}
}
# 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"

76
ihatemoney/bin/activate Normal file
View file

@ -0,0 +1,76 @@
# 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
# This should detect bash and zsh, which have a hash command that must
# be called to get it to forget past commands. Without forgetting
# past commands the $PATH changes we made may not be respected
if [ -n "${BASH:-}" -o -n "${ZSH_VERSION:-}" ] ; then
hash -r
fi
if [ -n "${_OLD_VIRTUAL_PS1:-}" ] ; then
PS1="${_OLD_VIRTUAL_PS1:-}"
export PS1
unset _OLD_VIRTUAL_PS1
fi
unset VIRTUAL_ENV
if [ ! "${1:-}" = "nondestructive" ] ; then
# Self destruct!
unset -f deactivate
fi
}
# unset irrelevant variables
deactivate nondestructive
VIRTUAL_ENV="/Users/wenxintian/Desktop/Fall2023/EECS481/ihatemoney/ihatemoney"
export VIRTUAL_ENV
_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:-}"
if [ "x(ihatemoney) " != x ] ; then
PS1="(ihatemoney) ${PS1:-}"
else
if [ "`basename \"$VIRTUAL_ENV\"`" = "__" ] ; then
# special case for Aspen magic directories
# see https://aspen.io/
PS1="[`basename \`dirname \"$VIRTUAL_ENV\"\``] $PS1"
else
PS1="(`basename \"$VIRTUAL_ENV\"`)$PS1"
fi
fi
export PS1
fi
# This should detect bash and zsh, which have a hash command that must
# be called to get it to forget past commands. Without forgetting
# past commands the $PATH changes we made may not be respected
if [ -n "${BASH:-}" -o -n "${ZSH_VERSION:-}" ] ; then
hash -r
fi

View file

@ -0,0 +1,37 @@
# 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; test "\!:*" != "nondestructive" && unalias deactivate'
# Unset irrelevant variables.
deactivate nondestructive
setenv VIRTUAL_ENV "/Users/wenxintian/Desktop/Fall2023/EECS481/ihatemoney/ihatemoney"
set _OLD_VIRTUAL_PATH="$PATH"
setenv PATH "$VIRTUAL_ENV/bin:$PATH"
set _OLD_VIRTUAL_PROMPT="$prompt"
if (! "$?VIRTUAL_ENV_DISABLE_PROMPT") then
if ("ihatemoney" != "") then
set env_name = "ihatemoney"
else
if (`basename "VIRTUAL_ENV"` == "__") then
# special case for Aspen magic directories
# see https://aspen.io/
set env_name = `basename \`dirname "$VIRTUAL_ENV"\``
else
set env_name = `basename "$VIRTUAL_ENV"`
endif
endif
set prompt = "[$env_name] $prompt"
unset env_name
endif
alias pydoc python -m pydoc
rehash

View file

@ -0,0 +1,75 @@
# This file must be used with ". bin/activate.fish" *from fish* (http://fishshell.org)
# you cannot run it directly
function deactivate -d "Exit virtualenv 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"
functions -e fish_prompt
set -e _OLD_FISH_PROMPT_OVERRIDE
functions -c _old_fish_prompt fish_prompt
functions -e _old_fish_prompt
end
set -e VIRTUAL_ENV
if test "$argv[1]" != "nondestructive"
# Self destruct!
functions -e deactivate
end
end
# unset irrelevant variables
deactivate nondestructive
set -gx VIRTUAL_ENV "/Users/wenxintian/Desktop/Fall2023/EECS481/ihatemoney/ihatemoney"
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
# Prompt override?
if test -n "(ihatemoney) "
printf "%s%s" "(ihatemoney) " (set_color normal)
else
# ...Otherwise, prepend env
set -l _checkbase (basename "$VIRTUAL_ENV")
if test $_checkbase = "__"
# special case for Aspen magic directories
# see https://aspen.io/
printf "%s[%s]%s " (set_color -b blue white) (basename (dirname "$VIRTUAL_ENV")) (set_color normal)
else
printf "%s(%s)%s" (set_color -b blue white) (basename "$VIRTUAL_ENV") (set_color normal)
end
end
# Restore the return status of the previous command.
echo "exit $old_status" | .
_old_fish_prompt
end
set -gx _OLD_FISH_PROMPT_OVERRIDE "$VIRTUAL_ENV"
end

8
ihatemoney/bin/alembic Executable file
View file

@ -0,0 +1,8 @@
#!/Users/wenxintian/Desktop/Fall2023/EECS481/ihatemoney/ihatemoney/bin/python3
# -*- coding: utf-8 -*-
import re
import sys
from alembic.config import main
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
sys.exit(main())

8
ihatemoney/bin/cmark Executable file
View file

@ -0,0 +1,8 @@
#!/Users/wenxintian/Desktop/Fall2023/EECS481/ihatemoney/ihatemoney/bin/python3
# -*- coding: utf-8 -*-
import re
import sys
from commonmark.cmark import main
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
sys.exit(main())

8
ihatemoney/bin/debts Executable file
View file

@ -0,0 +1,8 @@
#!/Users/wenxintian/Desktop/Fall2023/EECS481/ihatemoney/ihatemoney/bin/python3
# -*- coding: utf-8 -*-
import re
import sys
from debts.cli import main
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
sys.exit(main())

8
ihatemoney/bin/easy_install Executable file
View file

@ -0,0 +1,8 @@
#!/Users/wenxintian/Desktop/Fall2023/EECS481/ihatemoney/ihatemoney/bin/python3
# -*- coding: utf-8 -*-
import re
import sys
from setuptools.command.easy_install import main
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
sys.exit(main())

View file

@ -0,0 +1,8 @@
#!/Users/wenxintian/Desktop/Fall2023/EECS481/ihatemoney/ihatemoney/bin/python3
# -*- coding: utf-8 -*-
import re
import sys
from setuptools.command.easy_install import main
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
sys.exit(main())

8
ihatemoney/bin/email_validator Executable file
View file

@ -0,0 +1,8 @@
#!/Users/wenxintian/Desktop/Fall2023/EECS481/ihatemoney/ihatemoney/bin/python3
# -*- coding: utf-8 -*-
import re
import sys
from email_validator.__main__ import main
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
sys.exit(main())

8
ihatemoney/bin/flask Executable file
View file

@ -0,0 +1,8 @@
#!/Users/wenxintian/Desktop/Fall2023/EECS481/ihatemoney/ihatemoney/bin/python3
# -*- coding: utf-8 -*-
import re
import sys
from flask.cli import main
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
sys.exit(main())

33
ihatemoney/bin/ihatemoney Executable file
View file

@ -0,0 +1,33 @@
#!/Users/wenxintian/Desktop/Fall2023/EECS481/ihatemoney/ihatemoney/bin/python3
# EASY-INSTALL-ENTRY-SCRIPT: 'ihatemoney==6.1.3','console_scripts','ihatemoney'
import re
import sys
# for compatibility with easy_install; see #2198
__requires__ = 'ihatemoney==6.1.3'
try:
from importlib.metadata import distribution
except ImportError:
try:
from importlib_metadata import distribution
except ImportError:
from pkg_resources import load_entry_point
def importlib_load_entry_point(spec, group, name):
dist_name, _, _ = spec.partition('==')
matches = (
entry_point
for entry_point in distribution(dist_name).entry_points
if entry_point.group == group and entry_point.name == name
)
return next(matches).load()
globals().setdefault('load_entry_point', importlib_load_entry_point)
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
sys.exit(load_entry_point('ihatemoney==6.1.3', 'console_scripts', 'ihatemoney')())

8
ihatemoney/bin/mako-render Executable file
View file

@ -0,0 +1,8 @@
#!/Users/wenxintian/Desktop/Fall2023/EECS481/ihatemoney/ihatemoney/bin/python3
# -*- coding: utf-8 -*-
import re
import sys
from mako.cmd import cmdline
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
sys.exit(cmdline())

8
ihatemoney/bin/normalizer Executable file
View file

@ -0,0 +1,8 @@
#!/Users/wenxintian/Desktop/Fall2023/EECS481/ihatemoney/ihatemoney/bin/python3
# -*- coding: utf-8 -*-
import re
import sys
from charset_normalizer.cli import cli_detect
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
sys.exit(cli_detect())

8
ihatemoney/bin/pip Executable file
View file

@ -0,0 +1,8 @@
#!/Users/wenxintian/Desktop/Fall2023/EECS481/ihatemoney/ihatemoney/bin/python3
# -*- 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())

8
ihatemoney/bin/pip3 Executable file
View file

@ -0,0 +1,8 @@
#!/Users/wenxintian/Desktop/Fall2023/EECS481/ihatemoney/ihatemoney/bin/python3
# -*- 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())

8
ihatemoney/bin/pip3.8 Executable file
View file

@ -0,0 +1,8 @@
#!/Users/wenxintian/Desktop/Fall2023/EECS481/ihatemoney/ihatemoney/bin/python3
# -*- 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())

266
ihatemoney/bin/prichunkpng Executable file
View file

@ -0,0 +1,266 @@
#!/Users/wenxintian/Desktop/Fall2023/EECS481/ihatemoney/ihatemoney/bin/python3
# prichunkpng
# Chunk editing tool.
"""
Make a new PNG by adding, delete, or replacing particular chunks.
"""
import argparse
import collections
# https://docs.python.org/2.7/library/io.html
import io
import re
import string
import struct
import sys
import zlib
# Local module.
import png
Chunk = collections.namedtuple("Chunk", "type content")
class ArgumentError(Exception):
"""A user problem with the command arguments."""
def process(out, args):
"""Process the PNG file args.input to the output, chunk by chunk.
Chunks can be inserted, removed, replaced, or sometimes edited.
Chunks are specified by their 4 byte Chunk Type;
see https://www.w3.org/TR/2003/REC-PNG-20031110/#5Chunk-layout .
The chunks in args.delete will be removed from the stream.
The chunks in args.chunk will be inserted into the stream
with their contents taken from the named files.
Other options on the args object will create particular
ancillary chunks.
.gamma -> gAMA chunk
.sigbit -> sBIT chunk
Chunk types need not be official PNG chunks at all.
Non-standard chunks can be created.
"""
# Convert options to chunks in the args.chunk list
if args.gamma:
v = int(round(1e5 * args.gamma))
bs = io.BytesIO(struct.pack(">I", v))
args.chunk.insert(0, Chunk(b"gAMA", bs))
if args.sigbit:
v = struct.pack("%dB" % len(args.sigbit), *args.sigbit)
bs = io.BytesIO(v)
args.chunk.insert(0, Chunk(b"sBIT", bs))
if args.iccprofile:
# http://www.w3.org/TR/PNG/#11iCCP
v = b"a color profile\x00\x00" + zlib.compress(args.iccprofile.read())
bs = io.BytesIO(v)
args.chunk.insert(0, Chunk(b"iCCP", bs))
if args.transparent:
# https://www.w3.org/TR/2003/REC-PNG-20031110/#11tRNS
v = struct.pack(">%dH" % len(args.transparent), *args.transparent)
bs = io.BytesIO(v)
args.chunk.insert(0, Chunk(b"tRNS", bs))
if args.background:
# https://www.w3.org/TR/2003/REC-PNG-20031110/#11bKGD
v = struct.pack(">%dH" % len(args.background), *args.background)
bs = io.BytesIO(v)
args.chunk.insert(0, Chunk(b"bKGD", bs))
if args.physical:
# https://www.w3.org/TR/PNG/#11pHYs
numbers = re.findall(r"(\d+\.?\d*)", args.physical)
if len(numbers) not in {1, 2}:
raise ArgumentError("One or two numbers are required for --physical")
xppu = float(numbers[0])
if len(numbers) == 1:
yppu = xppu
else:
yppu = float(numbers[1])
unit_spec = 0
if args.physical.endswith("dpi"):
# Convert from DPI to Pixels Per Metre
# 1 inch is 0.0254 metres
l = 0.0254
xppu /= l
yppu /= l
unit_spec = 1
elif args.physical.endswith("ppm"):
unit_spec = 1
v = struct.pack("!LLB", round(xppu), round(yppu), unit_spec)
bs = io.BytesIO(v)
args.chunk.insert(0, Chunk(b"pHYs", bs))
# Create:
# - a set of chunks to delete
# - a dict of chunks to replace
# - a list of chunk to add
delete = set(args.delete)
# The set of chunks to replace are those where the specification says
# that there should be at most one of them.
replacing = set([b"gAMA", b"pHYs", b"sBIT", b"PLTE", b"tRNS", b"sPLT", b"IHDR"])
replace = dict()
add = []
for chunk in args.chunk:
if chunk.type in replacing:
replace[chunk.type] = chunk
else:
add.append(chunk)
input = png.Reader(file=args.input)
return png.write_chunks(out, edit_chunks(input.chunks(), delete, replace, add))
def edit_chunks(chunks, delete, replace, add):
"""
Iterate over chunks, yielding edited chunks.
Subtle: the new chunks have to have their contents .read().
"""
for type, v in chunks:
if type in delete:
continue
if type in replace:
yield type, replace[type].content.read()
del replace[type]
continue
if b"IDAT" <= type <= b"IDAT" and replace:
# If there are any chunks on the replace list by
# the time we reach IDAT, add then all now.
# put them all on the add list.
for chunk in replace.values():
yield chunk.type, chunk.content.read()
replace = dict()
if b"IDAT" <= type <= b"IDAT" and add:
# We reached IDAT; add all remaining chunks now.
for chunk in add:
yield chunk.type, chunk.content.read()
add = []
yield type, v
def chunk_name(s):
"""
Type check a chunk name option value.
"""
# See https://www.w3.org/TR/2003/REC-PNG-20031110/#table51
valid = len(s) == 4 and set(s) <= set(string.ascii_letters)
if not valid:
raise ValueError("Chunk name must be 4 ASCII letters")
return s.encode("ascii")
def comma_list(s):
"""
Convert s, a command separated list of whole numbers,
into a sequence of int.
"""
return tuple(int(v) for v in s.split(","))
def hex_color(s):
"""
Type check and convert a hex color.
"""
if s.startswith("#"):
s = s[1:]
valid = len(s) in [1, 2, 3, 4, 6, 12] and set(s) <= set(string.hexdigits)
if not valid:
raise ValueError("colour must be 1,2,3,4,6, or 12 hex-digits")
# For the 4-bit RGB, expand to 8-bit, by repeating digits.
if len(s) == 3:
s = "".join(c + c for c in s)
if len(s) in [1, 2, 4]:
# Single grey value.
return (int(s, 16),)
if len(s) in [6, 12]:
w = len(s) // 3
return tuple(int(s[i : i + w], 16) for i in range(0, len(s), w))
def main(argv=None):
if argv is None:
argv = sys.argv
argv = argv[1:]
parser = argparse.ArgumentParser()
parser.add_argument("--gamma", type=float, help="Gamma value for gAMA chunk")
parser.add_argument(
"--physical",
type=str,
metavar="x[,y][dpi|ppm]",
help="specify intended pixel size or aspect ratio",
)
parser.add_argument(
"--sigbit",
type=comma_list,
metavar="D[,D[,D[,D]]]",
help="Number of significant bits in each channel",
)
parser.add_argument(
"--iccprofile",
metavar="file.iccp",
type=argparse.FileType("rb"),
help="add an ICC Profile from a file",
)
parser.add_argument(
"--transparent",
type=hex_color,
metavar="#RRGGBB",
help="Specify the colour that is transparent (tRNS chunk)",
)
parser.add_argument(
"--background",
type=hex_color,
metavar="#RRGGBB",
help="background colour for bKGD chunk",
)
parser.add_argument(
"--delete",
action="append",
default=[],
type=chunk_name,
help="delete the chunk",
)
parser.add_argument(
"--chunk",
action="append",
nargs=2,
default=[],
type=str,
help="insert chunk, taking contents from file",
)
parser.add_argument(
"input", nargs="?", default="-", type=png.cli_open, metavar="PNG"
)
args = parser.parse_args(argv)
# Reprocess the chunk arguments, converting each pair into a Chunk.
args.chunk = [
Chunk(chunk_name(type), open(path, "rb")) for type, path in args.chunk
]
return process(png.binary_stdout(), args)
if __name__ == "__main__":
main()

81
ihatemoney/bin/pricolpng Executable file
View file

@ -0,0 +1,81 @@
#!/Users/wenxintian/Desktop/Fall2023/EECS481/ihatemoney/ihatemoney/bin/python3
# http://www.python.org/doc/2.4.4/lib/module-itertools.html
import itertools
import sys
import png
Description = """Join PNG images in a column top-to-bottom."""
class FormatError(Exception):
"""
Some problem with the image format.
"""
def join_col(out, l):
"""
Join the list of images.
All input images must be same width and
have the same number of channels.
They are joined top-to-bottom.
`out` is the (open file) destination for the output image.
`l` should be a list of open files (the input image files).
"""
image = 0
stream = 0
# When the first image is read, this will be the reference width,
# which must be the same for all images.
width = None
# Total height (accumulated as images are read).
height = 0
# Accumulated rows.
rows = []
for f in l:
stream += 1
while True:
im = png.Reader(file=f)
try:
im.preamble()
except EOFError:
break
image += 1
if not width:
width = im.width
elif width != im.width:
raise FormatError('Image %d in stream %d has width %d; does not match %d.' %
(image, stream, im.width, width))
height += im.height
# Various bugs here because different numbers of channels and depths go wrong.
w, h, p, info = im.asDirect()
rows.extend(p)
# Alarmingly re-use the last info object.
tinfo = dict(info)
del tinfo['size']
w = png.Writer(width, height, **tinfo)
w.write(out, rows)
def main(argv):
import argparse
parser = argparse.ArgumentParser(description=Description)
parser.add_argument(
"input", nargs="*", default="-", type=png.cli_open, metavar="PNG"
)
args = parser.parse_args()
return join_col(png.binary_stdout(), args.input)
if __name__ == '__main__':
main(sys.argv)

254
ihatemoney/bin/priditherpng Executable file
View file

@ -0,0 +1,254 @@
#!/Users/wenxintian/Desktop/Fall2023/EECS481/ihatemoney/ihatemoney/bin/python3
# pipdither
# Error Diffusing image dithering.
# Now with serpentine scanning.
# See http://www.efg2.com/Lab/Library/ImageProcessing/DHALF.TXT
# http://www.python.org/doc/2.4.4/lib/module-bisect.html
from bisect import bisect_left
import png
def dither(
out,
input,
bitdepth=1,
linear=False,
defaultgamma=1.0,
targetgamma=None,
cutoff=0.5, # see :cutoff:default
):
"""Dither the input PNG `inp` into an image with a smaller bit depth
and write the result image onto `out`. `bitdepth` specifies the bit
depth of the new image.
Normally the source image gamma is honoured (the image is
converted into a linear light space before being dithered), but
if the `linear` argument is true then the image is treated as
being linear already: no gamma conversion is done (this is
quicker, and if you don't care much about accuracy, it won't
matter much).
Images with no gamma indication (no ``gAMA`` chunk) are normally
treated as linear (gamma = 1.0), but often it can be better
to assume a different gamma value: For example continuous tone
photographs intended for presentation on the web often carry
an implicit assumption of being encoded with a gamma of about
0.45 (because that's what you get if you just "blat the pixels"
onto a PC framebuffer), so ``defaultgamma=0.45`` might be a
good idea. `defaultgamma` does not override a gamma value
specified in the file itself: It is only used when the file
does not specify a gamma.
If you (pointlessly) specify both `linear` and `defaultgamma`,
`linear` wins.
The gamma of the output image is, by default, the same as the input
image. The `targetgamma` argument can be used to specify a
different gamma for the output image. This effectively recodes the
image to a different gamma, dithering as we go. The gamma specified
is the exponent used to encode the output file (and appears in the
output PNG's ``gAMA`` chunk); it is usually less than 1.
"""
# Encoding is what happened when the PNG was made (and also what
# happens when we output the PNG). Decoding is what we do to the
# source PNG in order to process it.
# The dithering algorithm is not completely general; it
# can only do bit depth reduction, not arbitrary palette changes.
import operator
maxval = 2 ** bitdepth - 1
r = png.Reader(file=input)
_, _, pixels, info = r.asDirect()
planes = info["planes"]
# :todo: make an Exception
assert planes == 1
width = info["size"][0]
sourcemaxval = 2 ** info["bitdepth"] - 1
if linear:
gamma = 1
else:
gamma = info.get("gamma") or defaultgamma
# Calculate an effective gamma for input and output;
# then build tables using those.
# `gamma` (whether it was obtained from the input file or an
# assumed value) is the encoding gamma.
# We need the decoding gamma, which is the reciprocal.
decode = 1.0 / gamma
# `targetdecode` is the assumed gamma that is going to be used
# to decoding the target PNG.
# Note that even though we will _encode_ the target PNG we
# still need the decoding gamma, because
# the table we use maps from PNG pixel value to linear light level.
if targetgamma is None:
targetdecode = decode
else:
targetdecode = 1.0 / targetgamma
incode = build_decode_table(sourcemaxval, decode)
# For encoding, we still build a decode table, because we
# use it inverted (searching with bisect).
outcode = build_decode_table(maxval, targetdecode)
# The table used for choosing output codes. These values represent
# the cutoff points between two adjacent output codes.
# The cutoff parameter can be varied between 0 and 1 to
# preferentially choose lighter (when cutoff > 0.5) or
# darker (when cutoff < 0.5) values.
# :cutoff:default: The default for this used to be 0.75, but
# testing by drj on 2021-07-30 showed that this produces
# banding when dithering left-to-right gradients;
# test with:
# priforgepng grl | priditherpng | kitty icat
choosecode = list(zip(outcode[1:], outcode))
p = cutoff
choosecode = [x[0] * p + x[1] * (1.0 - p) for x in choosecode]
rows = repeat_header(pixels)
dithered_rows = run_dither(incode, choosecode, outcode, width, rows)
dithered_rows = remove_header(dithered_rows)
info["bitdepth"] = bitdepth
info["gamma"] = 1.0 / targetdecode
w = png.Writer(**info)
w.write(out, dithered_rows)
def build_decode_table(maxval, gamma):
"""Build a lookup table for decoding;
table converts from pixel values to linear space.
"""
assert maxval == int(maxval)
assert maxval > 0
f = 1.0 / maxval
table = [f * v for v in range(maxval + 1)]
if gamma != 1.0:
table = [v ** gamma for v in table]
return table
def run_dither(incode, choosecode, outcode, width, rows):
"""
Run an serpentine dither.
Using the incode and choosecode tables.
"""
# Errors diffused downwards (into next row)
ed = [0.0] * width
flipped = False
for row in rows:
# Convert to linear...
row = [incode[v] for v in row]
# Add errors...
row = [e + v for e, v in zip(ed, row)]
if flipped:
row = row[::-1]
targetrow = [0] * width
for i, v in enumerate(row):
# `it` will be the index of the chosen target colour;
it = bisect_left(choosecode, v)
targetrow[i] = it
t = outcode[it]
# err is the error that needs distributing.
err = v - t
# Sierra "Filter Lite" distributes * 2
# as per this diagram. 1 1
ef = err * 0.5
# :todo: consider making rows one wider at each end and
# removing "if"s
if i + 1 < width:
row[i + 1] += ef
ef *= 0.5
ed[i] = ef
if i:
ed[i - 1] += ef
if flipped:
ed = ed[::-1]
targetrow = targetrow[::-1]
yield targetrow
flipped = not flipped
WARMUP_ROWS = 32
def repeat_header(rows):
"""Repeat the first row, to "warm up" the error register."""
for row in rows:
yield row
for _ in range(WARMUP_ROWS):
yield row
break
yield from rows
def remove_header(rows):
"""Remove the same number of rows that repeat_header added."""
for _ in range(WARMUP_ROWS):
next(rows)
yield from rows
def main(argv=None):
import sys
# https://docs.python.org/3.5/library/argparse.html
import argparse
parser = argparse.ArgumentParser()
if argv is None:
argv = sys.argv
progname, *args = argv
parser.add_argument("--bitdepth", type=int, default=1, help="bitdepth of output")
parser.add_argument(
"--cutoff",
type=float,
default=0.5,
help="cutoff to select adjacent output values",
)
parser.add_argument(
"--defaultgamma",
type=float,
default=1.0,
help="gamma value to use when no gamma in input",
)
parser.add_argument("--linear", action="store_true", help="force linear input")
parser.add_argument(
"--targetgamma",
type=float,
help="gamma to use in output (target), defaults to input gamma",
)
parser.add_argument(
"input", nargs="?", default="-", type=png.cli_open, metavar="PNG"
)
ns = parser.parse_args(args)
return dither(png.binary_stdout(), **vars(ns))
if __name__ == "__main__":
main()

275
ihatemoney/bin/priforgepng Executable file
View file

@ -0,0 +1,275 @@
#!/Users/wenxintian/Desktop/Fall2023/EECS481/ihatemoney/ihatemoney/bin/python3
# priforgepng
"""Forge PNG image from raw computation."""
from array import array
from fractions import Fraction
import argparse
import re
import sys
import png
def gen_glr(x):
"""Gradient Left to Right"""
return x
def gen_grl(x):
"""Gradient Right to Left"""
return 1 - x
def gen_gtb(x, y):
"""Gradient Top to Bottom"""
return y
def gen_gbt(x, y):
"""Gradient Bottom to Top"""
return 1.0 - y
def gen_rtl(x, y):
"""Radial gradient, centred at Top-Left"""
return max(1 - (float(x) ** 2 + float(y) ** 2) ** 0.5, 0.0)
def gen_rctr(x, y):
"""Radial gradient, centred at Centre"""
return gen_rtl(float(x) - 0.5, float(y) - 0.5)
def gen_rtr(x, y):
"""Radial gradient, centred at Top-Right"""
return gen_rtl(1.0 - float(x), y)
def gen_rbl(x, y):
"""Radial gradient, centred at Bottom-Left"""
return gen_rtl(x, 1.0 - float(y))
def gen_rbr(x, y):
"""Radial gradient, centred at Bottom-Right"""
return gen_rtl(1.0 - float(x), 1.0 - float(y))
def stripe(x, n):
return int(x * n) & 1
def gen_vs2(x):
"""2 Vertical Stripes"""
return stripe(x, 2)
def gen_vs4(x):
"""4 Vertical Stripes"""
return stripe(x, 4)
def gen_vs10(x):
"""10 Vertical Stripes"""
return stripe(x, 10)
def gen_hs2(x, y):
"""2 Horizontal Stripes"""
return stripe(float(y), 2)
def gen_hs4(x, y):
"""4 Horizontal Stripes"""
return stripe(float(y), 4)
def gen_hs10(x, y):
"""10 Horizontal Stripes"""
return stripe(float(y), 10)
def gen_slr(x, y):
"""10 diagonal stripes, rising from Left to Right"""
return stripe(x + y, 10)
def gen_srl(x, y):
"""10 diagonal stripes, rising from Right to Left"""
return stripe(1 + x - y, 10)
def checker(x, y, n):
return stripe(x, n) ^ stripe(y, n)
def gen_ck8(x, y):
"""8 by 8 checkerboard"""
return checker(x, y, 8)
def gen_ck15(x, y):
"""15 by 15 checkerboard"""
return checker(x, y, 15)
def gen_zero(x):
"""All zero (black)"""
return 0
def gen_one(x):
"""All one (white)"""
return 1
def yield_fun_rows(size, bitdepth, pattern):
"""
Create a single channel (monochrome) test pattern.
Yield each row in turn.
"""
width, height = size
maxval = 2 ** bitdepth - 1
if maxval > 255:
typecode = "H"
else:
typecode = "B"
pfun = pattern_function(pattern)
# The coordinates are an integer + 0.5,
# effectively sampling each pixel at its centre.
# This is morally better, and produces all 256 sample values
# in a 256-pixel wide gradient.
# We make a list of x coordinates here and re-use it,
# because Fraction instances are slow to allocate.
xs = [Fraction(x, 2 * width) for x in range(1, 2 * width, 2)]
# The general case is a function in x and y,
# but if the function only takes an x argument,
# it's handled in a special case that is a lot faster.
if n_args(pfun) == 2:
for y in range(height):
a = array(typecode)
fy = Fraction(Fraction(y + 0.5), height)
for fx in xs:
a.append(int(round(maxval * pfun(fx, fy))))
yield a
return
# For functions in x only, it's a _lot_ faster
# to generate a single row and repeatedly yield it
a = array(typecode)
for fx in xs:
a.append(int(round(maxval * pfun(x=fx))))
for y in range(height):
yield a
return
def generate(args):
"""
Create a PNG test image and write the file to stdout.
`args` should be an argparse Namespace instance or similar.
"""
size = args.size
bitdepth = args.depth
out = png.binary_stdout()
for pattern in args.pattern:
rows = yield_fun_rows(size, bitdepth, pattern)
writer = png.Writer(
size[0], size[1], bitdepth=bitdepth, greyscale=True, alpha=False
)
writer.write(out, rows)
def n_args(fun):
"""Number of arguments in fun's argument list."""
return fun.__code__.co_argcount
def pattern_function(pattern):
"""From `pattern`, a string,
return the function for that pattern.
"""
lpat = pattern.lower()
for name, fun in globals().items():
parts = name.split("_")
if parts[0] != "gen":
continue
if parts[1] == lpat:
return fun
def patterns():
"""
List the patterns.
"""
for name, fun in globals().items():
parts = name.split("_")
if parts[0] == "gen":
yield parts[1], fun.__doc__
def dimensions(s):
"""
Typecheck the --size option, which should be
one or two comma separated numbers.
Example: "64,40".
"""
tupl = re.findall(r"\d+", s)
if len(tupl) not in (1, 2):
raise ValueError("%r should be width or width,height" % s)
if len(tupl) == 1:
tupl *= 2
assert len(tupl) == 2
return list(map(int, tupl))
def main(argv=None):
if argv is None:
argv = sys.argv
parser = argparse.ArgumentParser(description="Forge greyscale PNG patterns")
parser.add_argument(
"-l", "--list", action="store_true", help="print list of patterns and exit"
)
parser.add_argument(
"-d", "--depth", default=8, type=int, metavar="N", help="N bits per pixel"
)
parser.add_argument(
"-s",
"--size",
default=[256, 256],
type=dimensions,
metavar="w[,h]",
help="width and height of the image in pixels",
)
parser.add_argument("pattern", nargs="*", help="name of pattern")
args = parser.parse_args(argv[1:])
if args.list:
for name, doc in sorted(patterns()):
print(name, doc, sep="\t")
return
if not args.pattern:
parser.error("--list or pattern is required")
return generate(args)
if __name__ == "__main__":
main()

72
ihatemoney/bin/prigreypng Executable file
View file

@ -0,0 +1,72 @@
#!/Users/wenxintian/Desktop/Fall2023/EECS481/ihatemoney/ihatemoney/bin/python3
# prigreypng
# Convert image to grey (L, or LA), but only if that involves no colour change.
import argparse
import array
import png
def as_grey(out, inp):
"""
Convert image to greyscale, but only when no colour change.
This works by using the input G channel (green) as
the output L channel (luminance) and
checking that every pixel is grey as we go.
A non-grey pixel will raise an error.
"""
r = png.Reader(file=inp)
_, _, rows, info = r.asDirect()
if info["greyscale"]:
w = png.Writer(**info)
return w.write(out, rows)
planes = info["planes"]
targetplanes = planes - 2
alpha = info["alpha"]
width, height = info["size"]
typecode = "BH"[info["bitdepth"] > 8]
# Values per target row
vpr = width * targetplanes
def iterasgrey():
for i, row in enumerate(rows):
row = array.array(typecode, row)
targetrow = array.array(typecode, [0] * vpr)
# Copy G (and possibly A) channel.
green = row[0::planes]
if alpha:
targetrow[0::2] = green
targetrow[1::2] = row[3::4]
else:
targetrow = green
# Check R and B channel match.
if green != row[0::planes] or green != row[2::planes]:
raise ValueError("Row %i contains non-grey pixel." % i)
yield targetrow
info["greyscale"] = True
del info["planes"]
w = png.Writer(**info)
return w.write(out, iterasgrey())
def main(argv=None):
parser = argparse.ArgumentParser()
parser.add_argument(
"input", nargs="?", default="-", type=png.cli_open, metavar="PNG"
)
args = parser.parse_args()
return as_grey(png.binary_stdout(), args.input)
if __name__ == "__main__":
import sys
sys.exit(main())

111
ihatemoney/bin/pripalpng Executable file
View file

@ -0,0 +1,111 @@
#!/Users/wenxintian/Desktop/Fall2023/EECS481/ihatemoney/ihatemoney/bin/python3
# pripalpng
"""Convert to Palette PNG (without changing colours)"""
import argparse
import collections
# https://docs.python.org/2.7/library/io.html
import io
import string
import zlib
# Local module.
import png
def make_inverse_palette(rows, channels):
"""
The inverse palette maps from tuple to palette index.
"""
palette = {}
for row in rows:
for pixel in png.group(row, channels):
if pixel in palette:
continue
palette[pixel] = len(palette)
return palette
def palette_convert(out, inp, palette_file):
"""
Convert PNG image in `inp` to use a palette, colour type 3,
and write converted image to `out`.
`palette_file` is a file descriptor for the palette to use.
If `palette_file` is None, then `inp` is used as the palette.
"""
if palette_file is None:
inp, palette_file = palette_file, inp
reader = png.Reader(file=palette_file)
w, h, rows, info = asRGBorA8(reader)
channels = info["planes"]
if not inp:
rows = list(rows)
palette_map = make_inverse_palette(rows, channels)
if inp:
reader = png.Reader(file=inp)
w, h, rows, info = asRGBorA8(reader)
channels = info["planes"]
# Default for colours not in palette is to use last entry.
last = len(palette_map) - 1
def map_pixel(p):
return palette_map.get(p, last)
def convert_rows():
for row in rows:
yield [map_pixel(p) for p in png.group(row, channels)]
# Make a palette by sorting the pixels according to their index.
palette = sorted(palette_map.keys(), key=palette_map.get)
pal_info = dict(size=info["size"], palette=palette)
w = png.Writer(**pal_info)
w.write(out, convert_rows())
def asRGBorA8(reader):
"""
Return (width, height, rows, info) converting to RGB,
or RGBA if original has an alpha channel.
"""
_, _, _, info = reader.read()
if info["alpha"]:
return reader.asRGBA8()
else:
return reader.asRGB8()
def main(argv=None):
import sys
import re
if argv is None:
argv = sys.argv
argv = argv[1:]
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--palette", type=png.cli_open)
parser.add_argument(
"input", nargs="?", default="-", type=png.cli_open, metavar="PNG"
)
args = parser.parse_args(argv)
palette_convert(png.binary_stdout(), args.input, args.palette)
if __name__ == "__main__":
main()

355
ihatemoney/bin/pripamtopng Executable file
View file

@ -0,0 +1,355 @@
#!/Users/wenxintian/Desktop/Fall2023/EECS481/ihatemoney/ihatemoney/bin/python3
# pripamtopng
#
# Python Raster Image PAM to PNG
import array
import struct
import sys
import png
Description = """Convert NetPBM PAM/PNM format files to PNG."""
def read_pam_header(infile):
"""
Read (the rest of a) PAM header.
`infile` should be positioned immediately after the initial 'P7' line
(at the beginning of the second line).
Returns are as for `read_pnm_header`.
"""
# Unlike PBM, PGM, and PPM, we can read the header a line at a time.
header = dict()
while True:
line = infile.readline().strip()
if line == b"ENDHDR":
break
if not line:
raise EOFError("PAM ended prematurely")
if line[0] == b"#":
continue
line = line.split(None, 1)
key = line[0]
if key not in header:
header[key] = line[1]
else:
header[key] += b" " + line[1]
required = [b"WIDTH", b"HEIGHT", b"DEPTH", b"MAXVAL"]
required_str = b", ".join(required).decode("ascii")
result = []
for token in required:
if token not in header:
raise png.Error("PAM file must specify " + required_str)
try:
x = int(header[token])
except ValueError:
raise png.Error(required_str + " must all be valid integers")
if x <= 0:
raise png.Error(required_str + " must all be positive integers")
result.append(x)
return (b"P7",) + tuple(result)
def read_pnm_header(infile):
"""
Read a PNM header, returning (format,width,height,depth,maxval).
Also reads a PAM header (by using a helper function).
`width` and `height` are in pixels.
`depth` is the number of channels in the image;
for PBM and PGM it is synthesized as 1, for PPM as 3;
for PAM images it is read from the header.
`maxval` is synthesized (as 1) for PBM images.
"""
# Generally, see http://netpbm.sourceforge.net/doc/ppm.html
# and http://netpbm.sourceforge.net/doc/pam.html
# Technically 'P7' must be followed by a newline,
# so by using rstrip() we are being liberal in what we accept.
# I think this is acceptable.
magic = infile.read(3).rstrip()
if magic == b"P7":
# PAM header parsing is completely different.
return read_pam_header(infile)
# Expected number of tokens in header (3 for P4, 4 for P6)
expected = 4
pbm = (b"P1", b"P4")
if magic in pbm:
expected = 3
header = [magic]
# We must read the rest of the header byte by byte because
# the final whitespace character may not be a newline.
# Of course all PNM files in the wild use a newline at this point,
# but we are strong and so we avoid
# the temptation to use readline.
bs = bytearray()
backs = bytearray()
def next():
if backs:
c = bytes(backs[0:1])
del backs[0]
else:
c = infile.read(1)
if not c:
raise png.Error("premature EOF reading PNM header")
bs.extend(c)
return c
def backup():
"""Push last byte of token onto front of backs."""
backs.insert(0, bs[-1])
del bs[-1]
def ignore():
del bs[:]
def tokens():
ls = lexInit
while True:
token, ls = ls()
if token:
yield token
def lexInit():
c = next()
# Skip comments
if b"#" <= c <= b"#":
while c not in b"\n\r":
c = next()
ignore()
return None, lexInit
# Skip whitespace (that precedes a token)
if c.isspace():
ignore()
return None, lexInit
if not c.isdigit():
raise png.Error("unexpected byte %r found in header" % c)
return None, lexNumber
def lexNumber():
# According to the specification it is legal to have comments
# that appear in the middle of a token.
# I've never seen it; and,
# it's a bit awkward to code good lexers in Python (no goto).
# So we break on such cases.
c = next()
while c.isdigit():
c = next()
backup()
token = bs[:]
ignore()
return token, lexInit
for token in tokens():
# All "tokens" are decimal integers, so convert them here.
header.append(int(token))
if len(header) == expected:
break
final = next()
if not final.isspace():
raise png.Error("expected header to end with whitespace, not %r" % final)
if magic in pbm:
# synthesize a MAXVAL
header.append(1)
depth = (1, 3)[magic == b"P6"]
return header[0], header[1], header[2], depth, header[3]
def convert_pnm_plain(w, infile, outfile):
"""
Convert a plain PNM file containing raw pixel data into
a PNG file with the parameters set in the writer object.
Works for plain PGM formats.
"""
# See convert_pnm_binary for the corresponding function for
# binary PNM formats.
rows = scan_rows_from_file_plain(infile, w.width, w.height, w.planes)
w.write(outfile, rows)
def scan_rows_from_file_plain(infile, width, height, planes):
"""
Generate a sequence of rows from the input file `infile`.
The input file should be in a "Netpbm-like" plain format.
The input file should be positioned at the beginning of the
first value (that is, immediately after the header).
The number of pixels to read is taken from
the image dimensions (`width`, `height`, `planes`).
Each row is yielded as a single sequence of values.
"""
# Values per row
vpr = width * planes
values = []
rows_output = 0
# The core problem is that input lines (text lines) may not
# correspond with pixel rows. We use two nested loops.
# The outer loop reads the input one text line at a time;
# this will contain a whole number of values, which are
# added to the `values` list.
# The inner loop strips the first `vpr` values from the
# list, until there aren't enough.
# Note we can't tell how many iterations the inner loop will
# run for, it could be 0 (if not enough values were read to
# make a whole pixel row) or many (if the entire image were
# on one input line), or somewhere in between.
# In PNM there is in general no requirement to have
# correspondence between text lines and pixel rows.
for inp in infile:
values.extend(map(int, inp.split()))
while len(values) >= vpr:
yield values[:vpr]
del values[:vpr]
rows_output += 1
if rows_output >= height:
# Diagnostic here if there are spare values?
return
# Diagnostic here for early EOF?
def convert_pnm_binary(w, infile, outfile):
"""
Convert a PNM file containing raw pixel data into
a PNG file with the parameters set in the writer object.
Works for (binary) PGM, PPM, and PAM formats.
"""
rows = scan_rows_from_file(infile, w.width, w.height, w.planes, w.bitdepth)
w.write(outfile, rows)
def scan_rows_from_file(infile, width, height, planes, bitdepth):
"""
Generate a sequence of rows from the input file `infile`.
The input file should be in a "Netpbm-like" binary format.
The input file should be positioned at the beginning of the first pixel.
The number of pixels to read is taken from
the image dimensions (`width`, `height`, `planes`);
the number of bytes per value is implied by `bitdepth`.
Each row is yielded as a single sequence of values.
"""
# Values per row
vpr = width * planes
# Bytes per row
bpr = vpr
if bitdepth > 8:
assert bitdepth == 16
bpr *= 2
fmt = ">%dH" % vpr
def line():
return array.array("H", struct.unpack(fmt, infile.read(bpr)))
else:
def line():
return array.array("B", infile.read(bpr))
for y in range(height):
yield line()
def parse_args(args):
"""
Create a parser and parse the command line arguments.
"""
from argparse import ArgumentParser
parser = ArgumentParser(description=Description)
version = "%(prog)s " + png.__version__
parser.add_argument("--version", action="version", version=version)
parser.add_argument(
"-c",
"--compression",
type=int,
metavar="level",
help="zlib compression level (0-9)",
)
parser.add_argument(
"input",
nargs="?",
default="-",
type=png.cli_open,
metavar="PAM/PNM",
help="input PAM/PNM file to convert",
)
args = parser.parse_args(args)
return args
def main(argv=None):
if argv is None:
argv = sys.argv
args = parse_args(argv[1:])
# Prepare input and output files
infile = args.input
# Call after parsing, so that --version and --help work.
outfile = png.binary_stdout()
# Encode PNM to PNG
format, width, height, depth, maxval = read_pnm_header(infile)
ok_formats = (b"P2", b"P5", b"P6", b"P7")
if format not in ok_formats:
raise NotImplementedError("file format %s not supported" % format)
# The NetPBM depth (number of channels) completely
# determines the PNG format.
# Observe:
# - L, LA, RGB, RGBA are the 4 modes supported by PNG;
# - they correspond to 1, 2, 3, 4 channels respectively.
# We use the number of channels in the source image to
# determine which one we have.
# We ignore the NetPBM image type and the PAM TUPLTYPE.
greyscale = depth <= 2
pamalpha = depth in (2, 4)
supported = [2 ** x - 1 for x in range(1, 17)]
try:
mi = supported.index(maxval)
except ValueError:
raise NotImplementedError(
"input maxval (%s) not in supported list %s" % (maxval, str(supported))
)
bitdepth = mi + 1
writer = png.Writer(
width,
height,
greyscale=greyscale,
bitdepth=bitdepth,
alpha=pamalpha,
compression=args.compression,
)
plain = format in (b"P1", b"P2", b"P3")
if plain:
convert_pnm_plain(writer, infile, outfile)
else:
convert_pnm_binary(writer, infile, outfile)
if __name__ == "__main__":
try:
sys.exit(main())
except png.Error as e:
print(e, file=sys.stderr)
sys.exit(99)

540
ihatemoney/bin/priplan9topng Executable file
View file

@ -0,0 +1,540 @@
#!/Users/wenxintian/Desktop/Fall2023/EECS481/ihatemoney/ihatemoney/bin/python3
# Imported from //depot/prj/plan9topam/master/code/plan9topam.py#4 on
# 2009-06-15.
"""Command line tool to convert from Plan 9 image format to PNG format.
Plan 9 image format description:
https://plan9.io/magic/man2html/6/image
Where possible this tool will use unbuffered read() calls,
so that when finished the file offset is exactly at the end of
the image data.
This is useful for Plan9 subfont files which place font metric
data immediately after the image.
"""
# Test materials
# asset/left.bit is a Plan 9 image file, a leftwards facing Glenda.
# Other materials have to be scrounged from the internet.
# https://plan9.io/sources/plan9/sys/games/lib/sokoban/images/cargo.bit
import array
import collections
import io
# http://www.python.org/doc/2.3.5/lib/module-itertools.html
import itertools
import os
# http://www.python.org/doc/2.3.5/lib/module-re.html
import re
import struct
# http://www.python.org/doc/2.3.5/lib/module-sys.html
import sys
# https://docs.python.org/3/library/tarfile.html
import tarfile
# https://pypi.org/project/pypng/
import png
# internal
import prix
class Error(Exception):
"""Some sort of Plan 9 image error."""
def block(s, n):
return zip(*[iter(s)] * n)
def plan9_as_image(inp):
"""Represent a Plan 9 image file as a png.Image instance, so
that it can be written as a PNG file.
Works with compressed input files and may work with uncompressed files.
"""
# Use inp.raw if available.
# This avoids buffering and means that when the image is processed,
# the resulting input stream is cued up exactly at the end
# of the image.
inp = getattr(inp, "raw", inp)
info, blocks = plan9_open_image(inp)
rows, infodict = plan9_image_rows(blocks, info)
return png.Image(rows, infodict)
def plan9_open_image(inp):
"""Open a Plan9 image file (`inp` should be an already open
file object), and return (`info`, `blocks`) pair.
`info` should be a Plan9 5-tuple;
`blocks` is the input, and it should yield (`row`, `data`)
pairs (see :meth:`pixmeta`).
"""
r = inp.read(11)
if r == b"compressed\n":
info, blocks = decompress(inp)
else:
# Since Python 3, there is a good chance that this path
# doesn't work.
info, blocks = glue(inp, r)
return info, blocks
def glue(f, r):
"""Return (info, stream) pair, given `r` the initial portion of
the metadata that has already been read from the stream `f`.
"""
r = r + f.read(60 - len(r))
return (meta(r), f)
def meta(r):
"""Convert 60 byte bytestring `r`, the metadata from an image file.
Returns a 5-tuple (*chan*,*minx*,*miny*,*limx*,*limy*).
5-tuples may settle into lists in transit.
As per https://plan9.io/magic/man2html/6/image the metadata
comprises 5 words separated by blanks.
As it happens each word starts at an index that is a multiple of 12,
but this routine does not care about that.
"""
r = r.split()
# :todo: raise FormatError
if 5 != len(r):
raise Error("Expected 5 space-separated words in metadata")
r = [r[0]] + [int(x) for x in r[1:]]
return r
def bitdepthof(chan):
"""Return the bitdepth for a Plan9 pixel format string."""
maxd = 0
for c in re.findall(rb"[a-z]\d*", chan):
if c[0] != "x":
maxd = max(maxd, int(c[1:]))
return maxd
def maxvalof(chan):
"""Return the netpbm MAXVAL for a Plan9 pixel format string."""
bitdepth = bitdepthof(chan)
return (2 ** bitdepth) - 1
def plan9_image_rows(blocks, metadata):
"""
Convert (uncompressed) Plan 9 image file to pair of (*rows*, *info*).
This is intended to be used by PyPNG format.
*info* is the image info (metadata) returned in a dictionary,
*rows* is an iterator that yields each row in
boxed row flat pixel format.
`blocks`, should be an iterator of (`row`, `data`) pairs.
"""
chan, minx, miny, limx, limy = metadata
rows = limy - miny
width = limx - minx
nchans = len(re.findall(b"[a-wyz]", chan))
alpha = b"a" in chan
# Iverson's convention for the win!
ncolour = nchans - alpha
greyscale = ncolour == 1
bitdepth = bitdepthof(chan)
maxval = maxvalof(chan)
# PNG style info dict.
meta = dict(
size=(width, rows),
bitdepth=bitdepth,
greyscale=greyscale,
alpha=alpha,
planes=nchans,
)
arraycode = "BH"[bitdepth > 8]
return (
map(
lambda x: array.array(arraycode, itertools.chain(*x)),
block(unpack(blocks, rows, width, chan, maxval), width),
),
meta,
)
def unpack(f, rows, width, chan, maxval):
"""Unpack `f` into pixels.
`chan` describes the pixel format using
the Plan9 syntax ("k8", "r8g8b8", and so on).
Assumes the pixel format has a total channel bit depth
that is either a multiple or a divisor of 8
(the Plan9 image specification requires this).
`f` should be an iterator that returns blocks of input such that
each block contains a whole number of pixels.
The return value is an iterator that yields each pixel as an n-tuple.
"""
def mask(w):
"""An integer, to be used as a mask, with bottom `w` bits set to 1."""
return (1 << w) - 1
def deblock(f, depth, width):
"""A "packer" used to convert multiple bytes into single pixels.
`depth` is the pixel depth in bits (>= 8), `width` is the row width in
pixels.
"""
w = depth // 8
i = 0
for block in f:
for i in range(len(block) // w):
p = block[w * i : w * (i + 1)]
i += w
# Convert little-endian p to integer x
x = 0
s = 1 # scale
for j in p:
x += s * j
s <<= 8
yield x
def bitfunge(f, depth, width):
"""A "packer" used to convert single bytes into multiple pixels.
Depth is the pixel depth (< 8), width is the row width in pixels.
"""
assert 8 / depth == 8 // depth
for block in f:
col = 0
for x in block:
for j in range(8 // depth):
yield x >> (8 - depth)
col += 1
if col == width:
# A row-end forces a new byte even if
# we haven't consumed all of the current byte.
# Effectively rows are bit-padded to make
# a whole number of bytes.
col = 0
break
x <<= depth
# number of bits in each channel
bits = [int(d) for d in re.findall(rb"\d+", chan)]
# colr of each channel
# (r, g, b, k for actual colours, and
# a, m, x for alpha, map-index, and unused)
colr = re.findall(b"[a-z]", chan)
depth = sum(bits)
# Select a "packer" that either:
# - gathers multiple bytes into a single pixel (for depth >= 8); or,
# - splits bytes into several pixels (for depth < 8).
if depth >= 8:
assert depth % 8 == 0
packer = deblock
else:
assert 8 % depth == 0
packer = bitfunge
for x in packer(f, depth, width):
# x is the pixel as an unsigned integer
o = []
# This is a bit yucky.
# Extract each channel from the _most_ significant part of x.
for b, col in zip(bits, colr):
v = (x >> (depth - b)) & mask(b)
x <<= b
if col != "x":
# scale to maxval
v = v * float(maxval) / mask(b)
v = int(v + 0.5)
o.append(v)
yield o
def decompress(f):
"""Decompress a Plan 9 image file.
The input `f` should be a binary file object that
is already cued past the initial 'compressed\n' string.
The return result is (`info`, `blocks`);
`info` is a 5-tuple of the Plan 9 image metadata;
`blocks` is an iterator that yields a (row, data) pair
for each block of data.
"""
r = meta(f.read(60))
return r, decomprest(f, r[4])
def decomprest(f, rows):
"""Iterator that decompresses the rest of a file once the metadata
have been consumed."""
row = 0
while row < rows:
row, o = deblock(f)
yield o
def deblock(f):
"""Decompress a single block from a compressed Plan 9 image file.
Each block starts with 2 decimal strings of 12 bytes each.
Yields a sequence of (row, data) pairs where
`row` is the total number of rows processed
(according to the file format) and
`data` is the decompressed data for this block.
"""
row = int(f.read(12))
size = int(f.read(12))
if not (0 <= size <= 6000):
raise Error("block has invalid size; not a Plan 9 image file?")
# Since each block is at most 6000 bytes we may as well read it all in
# one go.
d = f.read(size)
i = 0
o = []
while i < size:
x = d[i]
i += 1
if x & 0x80:
x = (x & 0x7F) + 1
lit = d[i : i + x]
i += x
o.extend(lit)
continue
# x's high-order bit is 0
length = (x >> 2) + 3
# Offset is made from bottom 2 bits of x and 8 bits of next byte.
# MSByte LSByte
# +---------------------+-------------------------+
# | - - - - - - | x1 x0 | d7 d6 d5 d4 d3 d2 d1 d0 |
# +-----------------------------------------------+
# Had to discover by inspection which way round the bits go,
# because https://plan9.io/magic/man2html/6/image doesn't say.
# that x's 2 bits are most significant.
offset = (x & 3) << 8
offset |= d[i]
i += 1
# Note: complement operator neatly maps (0 to 1023) to (-1 to
# -1024). Adding len(o) gives a (non-negative) offset into o from
# which to start indexing.
offset = ~offset + len(o)
if offset < 0:
raise Error(
"byte offset indexes off the begininning of "
"the output buffer; not a Plan 9 image file?"
)
for j in range(length):
o.append(o[offset + j])
return row, bytes(o)
FontChar = collections.namedtuple("FontChar", "x top bottom left width")
def font_copy(inp, image, out, control):
"""
Convert a Plan 9 font (`inp`, `image`) to a series of PNG images,
and write them out as a tar file to the file object `out`.
Write a text control file out to the file object `control`.
Each valid glyph in the font becomes a single PNG image;
the output is a tar file of all the images.
A Plan 9 font consists of a Plan 9 image immediately
followed by font data.
The image for the font should be the `image` argument,
the file containing the rest of the font data should be the
file object `inp` which should be cued up to the start of
the font data that immediately follows the image.
https://plan9.io/magic/man2html/6/font
"""
# The format is a little unusual, and isn't completely
# clearly documented.
# Each 6-byte structure (see FontChar above) defines
# a rectangular region of the image that is used for each
# glyph.
# The source image region that is used may be strictly
# smaller than the rectangle for the target glyph.
# This seems like a micro-optimisation.
# For each glyph,
# rows above `top` and below `bottom` will not be copied
# from the source (they can be assumed to be blank).
# No space is saved in the source image, since the rows must
# be present.
# `x` is always non-decreasing, so the glyphs appear strictly
# left-to-image in the source image.
# The x of the next glyph is used to
# infer the width of the source rectangle.
# `top` and `bottom` give the y-coordinate of the top- and
# bottom- sides of the rectangle in both source and targets.
# `left` is the x-coordinate of the left-side of the
# rectangle in the target glyph. (equivalently, the amount
# of padding that should be added on the left).
# `width` is the advance-width of the glyph; by convention
# it is 0 for an undefined glyph.
name = getattr(inp, "name", "*subfont*name*not*supplied*")
header = inp.read(36)
n, height, ascent = [int(x) for x in header.split()]
print("baseline", name, ascent, file=control, sep=",")
chs = []
for i in range(n + 1):
bs = inp.read(6)
ch = FontChar(*struct.unpack("<HBBBB", bs))
chs.append(ch)
tar = tarfile.open(mode="w|", fileobj=out)
# Start at 0, increment for every image output
# (recall that not every input glyph has an output image)
output_index = 0
for i in range(n):
ch = chs[i]
if ch.width == 0:
continue
print("png", "index", output_index, "glyph", name, i, file=control, sep=",")
info = dict(image.info, size=(ch.width, height))
target = new_image(info)
source_width = chs[i + 1].x - ch.x
rect = ((ch.left, ch.top), (ch.left + source_width, ch.bottom))
image_draw(target, rect, image, (ch.x, ch.top))
# :todo: add source, glyph, and baseline data here (as a
# private tag?)
o = io.BytesIO()
target.write(o)
binary_size = o.tell()
o.seek(0)
tarinfo = tar.gettarinfo(arcname="%s/glyph%d.png" % (name, i), fileobj=inp)
tarinfo.size = binary_size
tar.addfile(tarinfo, fileobj=o)
output_index += 1
tar.close()
def new_image(info):
"""Return a fresh png.Image instance."""
width, height = info["size"]
vpr = width * info["planes"]
row = lambda: [0] * vpr
rows = [row() for _ in range(height)]
return png.Image(rows, info)
def image_draw(target, rect, source, point):
"""The point `point` in the source image is aligned with the
top-left of rect in the target image, and then the rectangle
in target is replaced with the pixels from `source`.
This routine assumes that both source and target can have
their rows objects indexed (not streamed).
"""
# :todo: there is no attempt to do clipping or channel or
# colour conversion. But maybe later?
if target.info["planes"] != source.info["planes"]:
raise NotImplementedError(
"source and target must have the same number of planes"
)
if target.info["bitdepth"] != source.info["bitdepth"]:
raise NotImplementedError("source and target must have the same bitdepth")
tl, br = rect
left, top = tl
right, bottom = br
height = bottom - top
planes = source.info["planes"]
vpr = (right - left) * planes
source_left, source_top = point
source_l = source_left * planes
source_r = source_l + vpr
target_l = left * planes
target_r = target_l + vpr
for y in range(height):
row = source.rows[y + source_top]
row = row[source_l:source_r]
target.rows[top + y][target_l:target_r] = row
def main(argv=None):
import argparse
parser = argparse.ArgumentParser(description="Convert Plan9 image to PNG")
parser.add_argument(
"input",
nargs="?",
default="-",
type=png.cli_open,
metavar="image",
help="image file in Plan 9 format",
)
parser.add_argument(
"--control",
default=os.path.devnull,
type=argparse.FileType("w"),
metavar="ControlCSV",
help="(when using --font) write a control CSV file to named file",
)
parser.add_argument(
"--font",
action="store_true",
help="process as Plan 9 subfont: output a tar file of PNGs",
)
args = parser.parse_args()
image = plan9_as_image(args.input)
image.stream()
if not args.font:
image.write(png.binary_stdout())
else:
font_copy(args.input, image, png.binary_stdout(), args.control)
if __name__ == "__main__":
sys.exit(main())

33
ihatemoney/bin/pripnglsch Executable file
View file

@ -0,0 +1,33 @@
#!/Users/wenxintian/Desktop/Fall2023/EECS481/ihatemoney/ihatemoney/bin/python3
# pripnglsch
# PNG List Chunks
import png
def list_chunks(out, inp):
r = png.Reader(file=inp)
for t, v in r.chunks():
add = ""
if len(v) <= 28:
add = " " + v.hex()
else:
add = " " + v[:26].hex() + "..."
t = t.decode("ascii")
print("%s %10d%s" % (t, len(v), add), file=out)
def main(argv=None):
import argparse
import sys
parser = argparse.ArgumentParser()
parser.add_argument(
"input", nargs="?", default="-", type=png.cli_open, metavar="PNG"
)
args = parser.parse_args()
return list_chunks(sys.stdout, args.input)
if __name__ == "__main__":
main()

101
ihatemoney/bin/pripngtopam Executable file
View file

@ -0,0 +1,101 @@
#!/Users/wenxintian/Desktop/Fall2023/EECS481/ihatemoney/ihatemoney/bin/python3
import struct
import png
def write_pnm(file, plain, rows, meta):
"""
Write a Netpbm PNM (or PAM) file.
*file* output file object;
*plain* (a bool) true if writing plain format (not possible for PAM);
*rows* an iterator for the rows;
*meta* the info dictionary.
"""
meta = dict(meta)
meta["maxval"] = 2 ** meta["bitdepth"] - 1
meta["width"], meta["height"] = meta["size"]
# Number of planes determines both image formats:
# 1 : L to PGM
# 2 : LA to PAM
# 3 : RGB to PPM
# 4 : RGBA to PAM
planes = meta["planes"]
# Assume inputs are from a PNG file.
assert planes in (1, 2, 3, 4)
if planes in (1, 3):
if 1 == planes:
# PGM
# Even if maxval is 1 we use PGM instead of PBM,
# to avoid converting data.
magic = "P5"
if plain:
magic = "P2"
else:
# PPM
magic = "P6"
if plain:
magic = "P3"
header = "{magic} {width:d} {height:d} {maxval:d}\n".format(magic=magic, **meta)
if planes in (2, 4):
# PAM
# See http://netpbm.sourceforge.net/doc/pam.html
if plain:
raise Exception("PAM (%d-plane) does not support plain format" % planes)
if 2 == planes:
tupltype = "GRAYSCALE_ALPHA"
else:
tupltype = "RGB_ALPHA"
header = (
"P7\nWIDTH {width:d}\nHEIGHT {height:d}\n"
"DEPTH {planes:d}\nMAXVAL {maxval:d}\n"
"TUPLTYPE {tupltype}\nENDHDR\n".format(tupltype=tupltype, **meta)
)
file.write(header.encode("ascii"))
# Values per row
vpr = planes * meta["width"]
if plain:
for row in rows:
row_b = b" ".join([b"%d" % v for v in row])
file.write(row_b)
file.write(b"\n")
else:
# format for struct.pack
fmt = ">%d" % vpr
if meta["maxval"] > 0xFF:
fmt = fmt + "H"
else:
fmt = fmt + "B"
for row in rows:
file.write(struct.pack(fmt, *row))
file.flush()
def main(argv=None):
import argparse
parser = argparse.ArgumentParser(description="Convert PNG to PAM")
parser.add_argument("--plain", action="store_true")
parser.add_argument(
"input", nargs="?", default="-", type=png.cli_open, metavar="PNG"
)
args = parser.parse_args()
# Encode PNG to PNM (or PAM)
image = png.Reader(file=args.input)
_, _, rows, info = image.asDirect()
write_pnm(png.binary_stdout(), args.plain, rows, info)
if __name__ == "__main__":
import sys
sys.exit(main())

71
ihatemoney/bin/prirowpng Executable file
View file

@ -0,0 +1,71 @@
#!/Users/wenxintian/Desktop/Fall2023/EECS481/ihatemoney/ihatemoney/bin/python3
# http://www.python.org/doc/2.4.4/lib/module-itertools.html
import itertools
import sys
import png
Description = """Join PNG images in a row left-to-right."""
class FormatError(Exception):
"""
Some problem with the image format.
"""
def join_row(out, l):
"""
Concatenate the list of images.
All input images must be same height and
have the same number of channels.
They are concatenated left-to-right.
`out` is the (open file) destination for the output image.
`l` should be a list of open files (the input image files).
"""
l = [png.Reader(file=f) for f in l]
# Ewgh, side effects.
for r in l:
r.preamble()
# The reference height; from the first image.
height = l[0].height
# The total target width
width = 0
for i,r in enumerate(l):
if r.height != height:
raise FormatError('Image %d, height %d, does not match %d.' %
(i, r.height, height))
width += r.width
# Various bugs here because different numbers of channels and depths go wrong.
pixel, info = zip(*[r.asDirect()[2:4] for r in l])
tinfo = dict(info[0])
del tinfo['size']
w = png.Writer(width, height, **tinfo)
def iter_all_rows():
for row in zip(*pixel):
# `row` is a sequence that has one row from each input image.
# list() is required here to hasten the lazy row building;
# not sure if that's a bug in PyPNG or not.
yield list(itertools.chain(*row))
w.write(out, iter_all_rows())
def main(argv):
import argparse
parser = argparse.ArgumentParser(description=Description)
parser.add_argument(
"input", nargs="*", default="-", type=png.cli_open, metavar="PNG"
)
args = parser.parse_args()
return join_row(png.binary_stdout(), args.input)
if __name__ == '__main__':
main(sys.argv)

215
ihatemoney/bin/priweavepng Executable file
View file

@ -0,0 +1,215 @@
#!/Users/wenxintian/Desktop/Fall2023/EECS481/ihatemoney/ihatemoney/bin/python3
# priweavepng
# Weave selected channels from input PNG files into
# a multi-channel output PNG.
import collections
import re
from array import array
import png
"""
priweavepng file1.png [file2.png ...]
The `priweavepng` tool combines channels from the input images and
weaves a selection of those channels into an output image.
Conceptually an intermediate image is formed consisting of
all channels of all input images in the order given on the command line
and in the order of each channel in its image.
Then from 1 to 4 channels are selected and
an image is output with those channels.
The limit on the number of selected channels is
imposed by the PNG image format.
The `-c n` option selects channel `n`.
Further channels can be selected either by repeating the `-c` option,
or using a comma separated list.
For example `-c 3,2,1` will select channels 3, 2, and 1 in that order;
if the input is an RGB PNG, this will swop the Red and Blue channels.
The order is significant, the order in which the options are given is
the order of the output channels.
It is permissible, and sometimes useful
(for example, grey to colour expansion, see below),
to repeat the same channel.
If no `-c` option is used the default is
to select all of the input channels, up to the first 4.
`priweavepng` does not care about the meaning of the channels
and treats them as a matrix of values.
The numer of output channels determines the colour mode of the PNG file:
L (1-channel, Grey), LA (2-channel, Grey+Alpha),
RGB (3-channel, Red+Green+Blue), RGBA (4-channel, Red+Green+Blue+Alpha).
The `priweavepng` tool can be used for a variety of
channel building, swopping, and extraction effects:
Combine 3 grayscale images into RGB colour:
priweavepng grey1.png grey2.png grey3.png
Swop Red and Blue channels in colour image:
priweavepng -c 3 -c 2 -c 1 rgb.png
Extract Green channel as a greyscale image:
priweavepng -c 2 rgb.png
Convert a greyscale image to a colour image (all grey):
priweavepng -c 1 -c 1 -c 1 grey.png
Add alpha mask from a separate (greyscale) image:
priweavepng rgb.png grey.png
Extract alpha mask into a separate (greyscale) image:
priweavepng -c 4 rgba.png
Steal alpha mask from second file and add to first.
Note that the intermediate image in this example has 7 channels:
priweavepng -c 1 -c 2 -c 3 -c 7 rgb.png rgba.png
Take Green channel from 3 successive colour images to make a new RGB image:
priweavepng -c 2 -c 5 -c 8 rgb1.png rgb2.png rgb3.png
"""
Image = collections.namedtuple("Image", "rows info")
# For each channel in the intermediate raster,
# model:
# - image: the input image (0-based);
# - i: the channel index within that image (0-based);
# - bitdepth: the bitdepth of this channel.
Channel = collections.namedtuple("Channel", "image i bitdepth")
class Error(Exception):
pass
def weave(out, args):
"""Stack the input PNG files and extract channels
into a single output PNG.
"""
paths = args.input
if len(paths) < 1:
raise Error("Required input is missing.")
# List of Image instances
images = []
# Channel map. Maps from channel number (starting from 1)
# to an (image_index, channel_index) pair.
channel_map = dict()
channel = 1
for image_index, path in enumerate(paths):
inp = png.cli_open(path)
rows, info = png.Reader(file=inp).asDirect()[2:]
rows = list(rows)
image = Image(rows, info)
images.append(image)
# A later version of PyPNG may intelligently support
# PNG files with heterogenous bitdepths.
# For now, assumes bitdepth of all channels in image
# is the same.
channel_bitdepth = (image.info["bitdepth"],) * image.info["planes"]
for i in range(image.info["planes"]):
channel_map[channel + i] = Channel(image_index, i, channel_bitdepth[i])
channel += image.info["planes"]
assert channel - 1 == sum(image.info["planes"] for image in images)
# If no channels, select up to first 4 as default.
if not args.channel:
args.channel = range(1, channel)[:4]
out_channels = len(args.channel)
if not (0 < out_channels <= 4):
raise Error("Too many channels selected (must be 1 to 4)")
alpha = out_channels in (2, 4)
greyscale = out_channels in (1, 2)
bitdepth = tuple(image.info["bitdepth"] for image in images)
arraytype = "BH"[max(bitdepth) > 8]
size = [image.info["size"] for image in images]
# Currently, fail unless all images same size.
if len(set(size)) > 1:
raise NotImplementedError("Cannot cope when sizes differ - sorry!")
size = size[0]
# Values per row, of output image
vpr = out_channels * size[0]
def weave_row_iter():
"""
Yield each woven row in turn.
"""
# The zip call creates an iterator that yields
# a tuple with each element containing the next row
# for each of the input images.
for row_tuple in zip(*(image.rows for image in images)):
# output row
row = array(arraytype, [0] * vpr)
# for each output channel select correct input channel
for out_channel_i, selection in enumerate(args.channel):
channel = channel_map[selection]
# incoming row (make it an array)
irow = array(arraytype, row_tuple[channel.image])
n = images[channel.image].info["planes"]
row[out_channel_i::out_channels] = irow[channel.i :: n]
yield row
w = png.Writer(
size[0],
size[1],
greyscale=greyscale,
alpha=alpha,
bitdepth=bitdepth,
interlace=args.interlace,
)
w.write(out, weave_row_iter())
def comma_list(s):
"""
Type and return a list of integers.
"""
return [int(c) for c in re.findall(r"\d+", s)]
def main(argv=None):
import argparse
import itertools
import sys
if argv is None:
argv = sys.argv
argv = argv[1:]
parser = argparse.ArgumentParser()
parser.add_argument(
"-c",
"--channel",
action="append",
type=comma_list,
help="list of channels to extract",
)
parser.add_argument("--interlace", action="store_true", help="write interlaced PNG")
parser.add_argument("input", nargs="+")
args = parser.parse_args(argv)
if args.channel:
args.channel = list(itertools.chain(*args.channel))
return weave(png.binary_stdout(), args)
if __name__ == "__main__":
main()

8
ihatemoney/bin/pybabel Executable file
View file

@ -0,0 +1,8 @@
#!/Users/wenxintian/Desktop/Fall2023/EECS481/ihatemoney/ihatemoney/bin/python3
# -*- coding: utf-8 -*-
import re
import sys
from babel.messages.frontend import main
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
sys.exit(main())

8
ihatemoney/bin/pygmentize Executable file
View file

@ -0,0 +1,8 @@
#!/Users/wenxintian/Desktop/Fall2023/EECS481/ihatemoney/ihatemoney/bin/python3
# -*- coding: utf-8 -*-
import re
import sys
from pygments.cmdline import main
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
sys.exit(main())

1
ihatemoney/bin/python Symbolic link
View file

@ -0,0 +1 @@
python3

1
ihatemoney/bin/python3 Symbolic link
View file

@ -0,0 +1 @@
/Users/wenxintian/opt/anaconda3/bin/python3

8
ihatemoney/bin/qr Executable file
View file

@ -0,0 +1,8 @@
#!/Users/wenxintian/Desktop/Fall2023/EECS481/ihatemoney/ihatemoney/bin/python3
# -*- coding: utf-8 -*-
import re
import sys
from qrcode.console_scripts import main
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
sys.exit(main())

View file

@ -7,7 +7,8 @@ import email_validator
from flask import request
from flask_babel import lazy_gettext as _
from flask_wtf.file import FileAllowed, FileField, FileRequired
from flask_wtf.form import FlaskForm
from flask_wtf.form import FlaskForm, Form
from wtforms import FieldList, FormField, BooleanField, Label
from markupsafe import Markup
from werkzeug.security import check_password_hash
from wtforms.fields import (
@ -64,6 +65,7 @@ def get_billform_for(project, set_default=True, **kwargs):
"""
form = BillForm(**kwargs)
print(**kwargs)
if form.original_currency.data is None:
form.original_currency.data = project.default_currency
@ -80,13 +82,18 @@ def get_billform_for(project, set_default=True, **kwargs):
]
active_members = [(m.id, m.name) for m in project.active_members]
form.payed_for.choices = form.payer.choices = active_members
form.payed_for.default = [m.id for m in project.active_members]
# form.payed_for.choices = form.payer.choices = active_members
form.payer.choices = active_members
# form.payed_for.default = [m.id for m in project.active_members]
if set_default and request.method == "GET":
form.set_default()
return form
# form.set_default()
print("i am in get")
for member in active_members:
temp = PayerDateForm()
form.payed_for.append_entry(temp)
return form, active_members
class CommaDecimalField(DecimalField):
@ -347,9 +354,15 @@ class ResetPasswordForm(FlaskForm):
)
submit = SubmitField(_("Reset password"))
class PayerDateForm(Form):
payer_check = BooleanField()
payer_start_date = DateField(_("Start Date"), validators=[DataRequired()], default=datetime.now)
payer_end_date = DateField(_("End Date"), validators=[DataRequired()], default=datetime.now)
class BillForm(FlaskForm):
date = DateField(_("When?"), validators=[DataRequired()], default=datetime.now)
# date = DateField(_("When?"), validators=[DataRequired()], default=datetime.now)
start_date = DateField(_("Start Date?"), validators=[DataRequired()], default=datetime.now)
end_date = DateField(_("End date?"), validators=[DataRequired()], default=datetime.now)
what = StringField(_("What?"), validators=[DataRequired()])
payer = SelectField(_("Who paid?"), validators=[DataRequired()], coerce=int)
amount = CalculatorStringField(_("How much?"), validators=[DataRequired()])
@ -361,31 +374,36 @@ class BillForm(FlaskForm):
validators=[Optional(), URL()],
description=_("A link to an external document, related to this bill"),
)
payed_for = SelectMultipleField(
_("For whom?"), validators=[DataRequired()], coerce=int
)
# payed_for = SelectMultipleField(
# _("For whom?"), validators=[DataRequired()], coerce=int
# )
payed_for = FieldList(FormField(PayerDateForm))
submit = SubmitField(_("Submit"))
submit2 = SubmitField(_("Submit and add a new one"))
def export(self, project):
def export(self, project,payed_for_data):
print('export')
return Bill(
amount=float(self.amount.data),
date=self.date.data,
date=self.start_date.data,
end_date=self.end_date.data,
external_link=self.external_link.data,
original_currency=str(self.original_currency.data),
owers=Person.query.get_by_ids(self.payed_for.data, project),
owers=Person.query.get_by_ids(payed_for_data, project),
payer_id=self.payer.data,
project_default_currency=project.default_currency,
what=self.what.data,
)
def save(self, bill, project):
def save(self, bill, payed_for_data, project):
print('save')
bill.payer_id = self.payer.data
bill.amount = self.amount.data
bill.what = self.what.data
bill.external_link = self.external_link.data
bill.date = self.date.data
bill.owers = Person.query.get_by_ids(self.payed_for.data, project)
bill.date = self.start_date.data
bill.end_date = self.end_date.data
bill.owers = Person.query.get_by_ids(payed_for_data, project)
bill.original_currency = self.original_currency.data
bill.converted_amount = self.currency_helper.exchange_currency(
bill.amount, bill.original_currency, project.default_currency
@ -393,13 +411,16 @@ class BillForm(FlaskForm):
return bill
def fill(self, bill, project):
print('fill')
self.payer.data = bill.payer_id
self.amount.data = bill.amount
self.what.data = bill.what
self.external_link.data = bill.external_link
self.original_currency.data = bill.original_currency
self.date.data = bill.date
self.payed_for.data = [int(ower.id) for ower in bill.owers]
self.start_date.data = bill.date
self.end_date.data = bill.end_date
# for pay in self.payed_for.data:
# self.payed_for.data = [int(ower.id) for ower in bill.owers]
self.original_currency.label = Label("original_currency", _("Currency"))
self.original_currency.description = _(
@ -410,7 +431,20 @@ class BillForm(FlaskForm):
)
def set_default(self):
self.payed_for.data = self.payed_for.default
# self.payed_for.data = self.payed_for.default
# for payed in self.payed_for:
# payed.payer.default = True
pass
def validate_start_date(self,field):
# Check end date is start date or is after start date
print("validate date check")
if field.data > self.end_date.data:
msg = _(
"Invalid start date or end date"
)
raise ValidationError(msg)
def validate_amount(self, field):
if decimal.Decimal(field.data) > decimal.MAX_EMAX:

60
ihatemoney/ihatemoney.cfg Normal file
View file

@ -0,0 +1,60 @@
# You can find more information about what these settings mean in the
# documentation, available online at
# http://ihatemoney.readthedocs.io/en/latest/installation.html#configuration
# Turn this on if you want to have more output on what's happening under the
# hood. DO NOT TURN IT ON IN PRODUCTION.
DEBUG = False
# The database URI, reprensenting the type of database and how to connect to it.
# Enter an absolute path here.
SQLALCHEMY_DATABASE_URI = 'sqlite:////Users/wenxintian/Desktop/Fall2023/EECS481/ihatemoney/ihatemoney.sqlite'
SQLACHEMY_ECHO = DEBUG
# Will likely become the default value in flask-sqlalchemy >=3 ; could be removed
# then:
SQLALCHEMY_TRACK_MODIFICATIONS = False
# This secret key is random and auto-generated, it protects cookies and user sessions
SECRET_KEY = "*az06oas)72%l0auny9(!x7r+l!xn_9vz!-()=wh#ulkw%ji^)"
# A python tuple describing the name and email adress of the sender of the mails.
MAIL_DEFAULT_SENDER = "Budget manager <admin@example.com>" # CUSTOMIZE
# A boolean that determines whether the admin email (MAIL_DEFAULT_SENDER) is
# shown in error messages.
SHOW_ADMIN_EMAIL = True
# If set to True, a demonstration project will be activated.
ACTIVATE_DEMO_PROJECT = True
# If not empty, the specified password must be entered to create new projects.
# DO NOT enter the password in cleartext. Generate a password hash with
# "ihatemoney generate_password_hash" instead.
ADMIN_PASSWORD = ""
# If set to True (default value) anyone can create a new project.
ALLOW_PUBLIC_PROJECT_CREATION = True
# If set to True, an administration dashboard is available.
ACTIVATE_ADMIN_DASHBOARD = False
# You can change the timezone used to display time. By default it will be
#derived from the server OS.
#BABEL_DEFAULT_TIMEZONE = "Europe/Paris"
# Enable secure cookies. Requires HTTPS. Disable if you run your ihatemoney
# service over plain HTTP.
SESSION_COOKIE_SECURE = True
# Set this to a URL path under which the application will be served. Defaults to "/"
APPLICATION_ROOT = "/"
# You can activate an optional CAPTCHA if you want to. It can be helpful
# to filter spammer bots.
ENABLE_CAPTCHA = False
# You may want to point to a special legal page, for instance to give information
# about GDPR, or how you handle the data of your users.
# Set this variable to the URL you want.
LEGAL_LINK = ""

View file

@ -0,0 +1,164 @@
/* -*- indent-tabs-mode: nil; tab-width: 4; -*- */
/* Greenlet object interface */
#ifndef Py_GREENLETOBJECT_H
#define Py_GREENLETOBJECT_H
#include <Python.h>
#ifdef __cplusplus
extern "C" {
#endif
/* This is deprecated and undocumented. It does not change. */
#define GREENLET_VERSION "1.0.0"
#ifndef GREENLET_MODULE
#define implementation_ptr_t void*
#endif
typedef struct _greenlet {
PyObject_HEAD
PyObject* weakreflist;
PyObject* dict;
implementation_ptr_t pimpl;
} PyGreenlet;
#define PyGreenlet_Check(op) (op && PyObject_TypeCheck(op, &PyGreenlet_Type))
/* C API functions */
/* Total number of symbols that are exported */
#define PyGreenlet_API_pointers 12
#define PyGreenlet_Type_NUM 0
#define PyExc_GreenletError_NUM 1
#define PyExc_GreenletExit_NUM 2
#define PyGreenlet_New_NUM 3
#define PyGreenlet_GetCurrent_NUM 4
#define PyGreenlet_Throw_NUM 5
#define PyGreenlet_Switch_NUM 6
#define PyGreenlet_SetParent_NUM 7
#define PyGreenlet_MAIN_NUM 8
#define PyGreenlet_STARTED_NUM 9
#define PyGreenlet_ACTIVE_NUM 10
#define PyGreenlet_GET_PARENT_NUM 11
#ifndef GREENLET_MODULE
/* This section is used by modules that uses the greenlet C API */
static void** _PyGreenlet_API = NULL;
# define PyGreenlet_Type \
(*(PyTypeObject*)_PyGreenlet_API[PyGreenlet_Type_NUM])
# define PyExc_GreenletError \
((PyObject*)_PyGreenlet_API[PyExc_GreenletError_NUM])
# define PyExc_GreenletExit \
((PyObject*)_PyGreenlet_API[PyExc_GreenletExit_NUM])
/*
* PyGreenlet_New(PyObject *args)
*
* greenlet.greenlet(run, parent=None)
*/
# define PyGreenlet_New \
(*(PyGreenlet * (*)(PyObject * run, PyGreenlet * parent)) \
_PyGreenlet_API[PyGreenlet_New_NUM])
/*
* PyGreenlet_GetCurrent(void)
*
* greenlet.getcurrent()
*/
# define PyGreenlet_GetCurrent \
(*(PyGreenlet * (*)(void)) _PyGreenlet_API[PyGreenlet_GetCurrent_NUM])
/*
* PyGreenlet_Throw(
* PyGreenlet *greenlet,
* PyObject *typ,
* PyObject *val,
* PyObject *tb)
*
* g.throw(...)
*/
# define PyGreenlet_Throw \
(*(PyObject * (*)(PyGreenlet * self, \
PyObject * typ, \
PyObject * val, \
PyObject * tb)) \
_PyGreenlet_API[PyGreenlet_Throw_NUM])
/*
* PyGreenlet_Switch(PyGreenlet *greenlet, PyObject *args)
*
* g.switch(*args, **kwargs)
*/
# define PyGreenlet_Switch \
(*(PyObject * \
(*)(PyGreenlet * greenlet, PyObject * args, PyObject * kwargs)) \
_PyGreenlet_API[PyGreenlet_Switch_NUM])
/*
* PyGreenlet_SetParent(PyObject *greenlet, PyObject *new_parent)
*
* g.parent = new_parent
*/
# define PyGreenlet_SetParent \
(*(int (*)(PyGreenlet * greenlet, PyGreenlet * nparent)) \
_PyGreenlet_API[PyGreenlet_SetParent_NUM])
/*
* PyGreenlet_GetParent(PyObject* greenlet)
*
* return greenlet.parent;
*
* This could return NULL even if there is no exception active.
* If it does not return NULL, you are responsible for decrementing the
* reference count.
*/
# define PyGreenlet_GetParent \
(*(PyGreenlet* (*)(PyGreenlet*)) \
_PyGreenlet_API[PyGreenlet_GET_PARENT_NUM])
/*
* deprecated, undocumented alias.
*/
# define PyGreenlet_GET_PARENT PyGreenlet_GetParent
# define PyGreenlet_MAIN \
(*(int (*)(PyGreenlet*)) \
_PyGreenlet_API[PyGreenlet_MAIN_NUM])
# define PyGreenlet_STARTED \
(*(int (*)(PyGreenlet*)) \
_PyGreenlet_API[PyGreenlet_STARTED_NUM])
# define PyGreenlet_ACTIVE \
(*(int (*)(PyGreenlet*)) \
_PyGreenlet_API[PyGreenlet_ACTIVE_NUM])
/* Macro that imports greenlet and initializes C API */
/* NOTE: This has actually moved to ``greenlet._greenlet._C_API``, but we
keep the older definition to be sure older code that might have a copy of
the header still works. */
# define PyGreenlet_Import() \
{ \
_PyGreenlet_API = (void**)PyCapsule_Import("greenlet._C_API", 0); \
}
#endif /* GREENLET_MODULE */
#ifdef __cplusplus
}
#endif
#endif /* !Py_GREENLETOBJECT_H */

View file

@ -0,0 +1,27 @@
Copyright (c) 2013-2023 by the Babel Team, see AUTHORS for more information.
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.

View file

@ -0,0 +1,38 @@
Metadata-Version: 2.1
Name: Babel
Version: 2.13.1
Summary: Internationalization utilities
Home-page: https://babel.pocoo.org/
Author: Armin Ronacher
Author-email: armin.ronacher@active-4.com
Maintainer: Aarni Koskela
Maintainer-email: akx@iki.fi
License: BSD-3-Clause
Project-URL: Source, https://github.com/python-babel/babel
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: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
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 :: 3.12
Classifier: Programming Language :: Python :: Implementation :: CPython
Classifier: Programming Language :: Python :: Implementation :: PyPy
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.7
License-File: LICENSE
Requires-Dist: pytz >=2015.7 ; python_version < "3.9"
Requires-Dist: setuptools ; python_version >= "3.12"
Provides-Extra: dev
Requires-Dist: pytest >=6.0 ; extra == 'dev'
Requires-Dist: pytest-cov ; extra == 'dev'
Requires-Dist: freezegun ~=1.0 ; extra == 'dev'
A collection of tools for internationalizing Python applications.

View file

@ -0,0 +1,886 @@
../../../bin/pybabel,sha256=CvtH6cZgZYBNXn1eNPmSNKtYWfqbvFT47mRzNHZ3Qo0,282
Babel-2.13.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
Babel-2.13.1.dist-info/LICENSE,sha256=kI4K1yBTrifB0X4zQL0Uz_m_k1mS7VZSbRfJg6tuevc,1531
Babel-2.13.1.dist-info/METADATA,sha256=yNGEHoeLTRYXlFdsNYTnbn-Bt2x3NNAi4HwyhbXwykY,1607
Babel-2.13.1.dist-info/RECORD,,
Babel-2.13.1.dist-info/WHEEL,sha256=yQN5g4mg4AybRjkgi-9yy4iQEFibGQmlz78Pik5Or-A,92
Babel-2.13.1.dist-info/entry_points.txt,sha256=V9FEYIY5z6b5JfCc2jeN7zdQMwNwuH7gvUrmF8OAG5I,695
Babel-2.13.1.dist-info/top_level.txt,sha256=mQO3vNkqlcYs_xRaL5EpRIy1IRjMp4N9_vdwmiemPXo,6
babel/__init__.py,sha256=sjcCbyVl76pv8jtOoQIn5G4OHFsjzzDo_JGneU5Boj0,863
babel/__pycache__/__init__.cpython-38.pyc,,
babel/__pycache__/core.cpython-38.pyc,,
babel/__pycache__/dates.cpython-38.pyc,,
babel/__pycache__/languages.cpython-38.pyc,,
babel/__pycache__/lists.cpython-38.pyc,,
babel/__pycache__/localedata.cpython-38.pyc,,
babel/__pycache__/numbers.cpython-38.pyc,,
babel/__pycache__/plural.cpython-38.pyc,,
babel/__pycache__/support.cpython-38.pyc,,
babel/__pycache__/units.cpython-38.pyc,,
babel/__pycache__/util.cpython-38.pyc,,
babel/core.py,sha256=gH-PxgGTdSmY1mdpoO1AVv-Pg7IaOJM66I6z1QgaxTo,43036
babel/dates.py,sha256=CUUKz2OyWr88YsADvHLh3Ex0MJYrP_1wvNYFSH8nW8Y,72718
babel/global.dat,sha256=-EOoX8lXOQF0O8GMRw6Ojj5wEKQU2xLlmwmq1LE6Kgw,260169
babel/languages.py,sha256=2LDTV9WizAuZVam0vfw-Q-QKYCQpF5DxLbmVoat7TKI,2844
babel/lists.py,sha256=mE-FsWxu7vf4X-N3KPPNPR2HLxzc5DypkrRBBdjWRO8,3015
babel/locale-data/af.dat,sha256=sVgbzj9V2lqyhT8P9l7av7IvnllunHMxeebN_bbs6Ao,197015
babel/locale-data/af_NA.dat,sha256=9staJ5BF4By_hNQh4xkzBSxSO-Bw5SfC77gjG4C9HJo,1423
babel/locale-data/af_ZA.dat,sha256=ZaMuNgUHOKLle56lUxFOGAAk8QM-_41nuazbqNu5kgg,608
babel/locale-data/agq.dat,sha256=mGm4OIwxbXYyz8iroZVZoBstz-ZX0xe8kl_aqo1daiU,17248
babel/locale-data/agq_CM.dat,sha256=AxBMSZitoHhaa6djMmFbp6iEPM8OUC04G77ZldkuHR8,609
babel/locale-data/ak.dat,sha256=tpCFVPu4WRO3hGHb_-Cfe2CQXWtQJdcPHzu4YluXspE,15728
babel/locale-data/ak_GH.dat,sha256=tuOpoiGUJqZ_Dlr8xlp9oIqsFL-YQrBQpDUfG5z3YQk,589
babel/locale-data/am.dat,sha256=f3g4OSEkcFl4Vh-t9aXK9RHmvEP0FvG1HnrZuRSloAI,221817
babel/locale-data/am_ET.dat,sha256=JHNCRHUTq_8VPokwz2uGwCZPGxUR23nJdDIzi_HFIbA,608
babel/locale-data/ann.dat,sha256=wOaMV7Pf_1V9sJaI960wWZ0i4xZ7_vmQVhUWzS5ePuo,710
babel/locale-data/ann_NG.dat,sha256=ewcsWP2GlH47hGKUGVeDq-cQuk-TlY2Mjqg23qBpT7M,590
babel/locale-data/ar.dat,sha256=Q4OrhXm6pxG0UXCrsL_HnXOwArJJyCTybgiIZB56qrU,389208
babel/locale-data/ar_001.dat,sha256=Y2HUeGZn8VV7DCPv6nXTWmkqTtzGxZxdvXYYiS5mU-o,1680
babel/locale-data/ar_AE.dat,sha256=XId1NTigYhDpgagRw7Bgs6JFwYS5JBK-WmM9GXVGmlM,995
babel/locale-data/ar_BH.dat,sha256=f1D15u-5clcZJvrqsnr2XShOLf6hw5hmR587r7hsKEs,651
babel/locale-data/ar_DJ.dat,sha256=NWt7QxMxsj1-zAsJ8aXWGT1SwzKayjlbB8TxvY8P-iA,629
babel/locale-data/ar_DZ.dat,sha256=1KdQGZH5ePC4W3nwrB1F2msNqVVnK0wYwfU-uqYAhXU,1713
babel/locale-data/ar_EG.dat,sha256=EUDxLyjz-znR56wvAE-_IvJX-2ou_ubS3KVU83SHa5Q,688
babel/locale-data/ar_EH.dat,sha256=OseNtW_AOGrIkKmxk2ufJXkpwOXsajJ4uyJAwUidL1g,589
babel/locale-data/ar_ER.dat,sha256=FK8yF8SloHQoOXNpaKlnEMsS9oG0j9dhDhiSwk7euCw,610
babel/locale-data/ar_IL.dat,sha256=TzNjvKnJXxJBRXR55WZ9yVxpHnN-2subVXqjeS7CX4I,1195
babel/locale-data/ar_IQ.dat,sha256=G4JR6ue3O7NNz7Hy2WKKiHg9lqhaHGjZA-UFq8N9TKs,2336
babel/locale-data/ar_JO.dat,sha256=K9WKy9urKZA7k6MIuprjN2Yu-VgySZVzK46jui9NYnY,2335
babel/locale-data/ar_KM.dat,sha256=e0ER6Yw-J2DOL7R8JKuTBpU0_46WK0jLBKpsG56UHgk,1161
babel/locale-data/ar_KW.dat,sha256=hsa41dETEsjs8XPCZkryiCFbPBLrv6aF5ya-ImPAT3g,651
babel/locale-data/ar_LB.dat,sha256=b4DWnwWjHST9MvfKnu6YaGhP2ghxjpZP5TQy7w_OGtU,2336
babel/locale-data/ar_LY.dat,sha256=rs8U7zFYfoxwD07WtkK6PO2OG3c-O6IhhPdBgwqfIZw,1648
babel/locale-data/ar_MA.dat,sha256=ufYSdBIy96F6zJND6kKZuilh00Lpu-z3txPDPhsgAIk,2007
babel/locale-data/ar_MR.dat,sha256=wjI22LINnrT_HVHqm1ZmJ9Ndb6bFBKvAFkeyvQ8tBi8,2173
babel/locale-data/ar_OM.dat,sha256=gsBDBEK35j4M3ualnSdL6tFD4-u3dSbJX1NtS7znQ_E,651
babel/locale-data/ar_PS.dat,sha256=tTTcOqje-rppgz46-DrkawXtoc9jIQ2vwyA8rRU2uDM,2273
babel/locale-data/ar_QA.dat,sha256=QI6pzsVjeY_nxkk8iKhy_DUzfBJrZFWoL9uYKM3L9CM,651
babel/locale-data/ar_SA.dat,sha256=yrzRCggElJ5o_4c0lC_kHaa4lvqj8ilpelA3Cn5synk,29569
babel/locale-data/ar_SD.dat,sha256=gUbUGVDm-V2a9ViTVska833oAys0b6Au-IJcoMo5leM,651
babel/locale-data/ar_SO.dat,sha256=fSiIj3lwo0FJU0dXbnFUNLPDvV_jejp86mHcLiGtiJ4,608
babel/locale-data/ar_SS.dat,sha256=eAaVq86grUAnWNST_u32IrhbryyjRvUo27UG0js6zS8,631
babel/locale-data/ar_SY.dat,sha256=4ge-CrqdFYfvu3VOdrvd7lRqhGDf2rPfTYkaNBaO4Ks,2335
babel/locale-data/ar_TD.dat,sha256=yVONNY9PuoKVCLjT0w0qp0NLO4kShNT9j9eM_uKtQYY,589
babel/locale-data/ar_TN.dat,sha256=J3SolHTZQ9_7HZGluj2jFu4odczgSZlOYU7spA670XY,1651
babel/locale-data/ar_YE.dat,sha256=tsYZG7eRROrZJyzc_jUbyxbMRT157S3ocGMh7eIiqsI,651
babel/locale-data/as.dat,sha256=yfjC3G6X3li3qbKXeVH7XgNYg8rfh8_Ynzledszs0v8,254131
babel/locale-data/as_IN.dat,sha256=BfzVFooc90N8ufCwaNAuKzefwYLUen0-o4wUafoLYc0,631
babel/locale-data/asa.dat,sha256=_GJJZYvYTC59PLfCA12EgRTJjDA7sSuMkb-UUhFtqpA,16046
babel/locale-data/asa_TZ.dat,sha256=aSECPcjC7UM3Bb4Cy16Et-RHtNrhlzGM_v4zNMGsreU,590
babel/locale-data/ast.dat,sha256=DMT0-a_yaiOt-RAP9DxJ5XJNA8mv8tRDInemAj0rsi4,215642
babel/locale-data/ast_ES.dat,sha256=x4OX34OA3ztvfnETdf49lKg6Gz2q6Lv17Lrf0G4EZ1Y,627
babel/locale-data/az.dat,sha256=Twvpmt6hhRFtCr5ZYamw6PoZFtuItn5fgm2q-fHWhMs,208566
babel/locale-data/az_Cyrl.dat,sha256=NAL-u3anOfqyi3Q-Vq4dtcQQpCgqMUYKokcUlnFImu8,38778
babel/locale-data/az_Cyrl_AZ.dat,sha256=yhmkFuYZLbGzV8Q155t3UrHn-rEqAR9LVmz1sQkKcSI,608
babel/locale-data/az_Latn.dat,sha256=EkZYNfi4vipZ7wH0cvvd1yvqOJxwCNtYADX0SgJMnAE,2225
babel/locale-data/az_Latn_AZ.dat,sha256=yhmkFuYZLbGzV8Q155t3UrHn-rEqAR9LVmz1sQkKcSI,608
babel/locale-data/bas.dat,sha256=AocYvh66QWd6CTrAwX4XE3RZdXAdv4qKxS7C8GIFV4k,17037
babel/locale-data/bas_CM.dat,sha256=NlquEbS-6vOPdnyIC4r5KRnEbj4Y0oaO56i3IeH2MmI,609
babel/locale-data/be.dat,sha256=-h2tZAOS4ZSMT-3RhcysB3nQRoqW246t4rmypdf8LAE,300069
babel/locale-data/be_BY.dat,sha256=0uCaBRRcbIS46dyiHK85UMi-k3b1b_uspOzBHMos2jM,608
babel/locale-data/be_TARASK.dat,sha256=Qevl9blemNV0GByiExK_GVebgr0EEjCHcU3l5PqFruQ,101382
babel/locale-data/bem.dat,sha256=CEpdnBsCjpGelAEVy83wV2SmV31E2r7LddukUFQH1uE,6430
babel/locale-data/bem_ZM.dat,sha256=VbAesm4_2wMn2EmWOW7etCOWlleqpkSAjjMOtKBlEcQ,590
babel/locale-data/bez.dat,sha256=KOIZzLg2DS9MWVx5PPS6cuj3vAjJs9GS38JCq1DAArc,16840
babel/locale-data/bez_TZ.dat,sha256=PHbB6bmtC5Wn46cFkmE8mjwuSUTr3gCxXkmFzqpiDRQ,590
babel/locale-data/bg.dat,sha256=tVa2E_OuDeezPg0T6YvSF7ccWaiL3Ooo33NHsRSQMUQ,251790
babel/locale-data/bg_BG.dat,sha256=rHaVmPZT-2n7w37ORQM31-InIsuCBYpv6xWIAc0akkk,626
babel/locale-data/bgc.dat,sha256=wVvUeGXzQqtL3zJozsd42L4y-lz1yoWALGK9xHnAA5o,2789
babel/locale-data/bgc_IN.dat,sha256=yDVdS6nKOY7VHIlISwA9UnvR7jv821z2pgJK23eddp0,632
babel/locale-data/bho.dat,sha256=6ki1A58n3_U02EoRmKJdXoBFRbQ9fNmiJ1fDYi7QQxE,3464
babel/locale-data/bho_IN.dat,sha256=XOOT-VR76DArlhln4h-GrRo-SYjrqDgmhZTQBAxduFc,632
babel/locale-data/bm.dat,sha256=Clp5DwH0y3lvvcWWeiLPJcPgNHlXCeFt3KC0y5rvVCQ,15769
babel/locale-data/bm_ML.dat,sha256=uOp8g5jSZ0dtvQRJ_GmriD3hafnqKpY-D8VhCY0lctk,589
babel/locale-data/bn.dat,sha256=my4Zh7NONbnC8huy6AiGCa470bu33qEKFruxREHE-eI,282760
babel/locale-data/bn_BD.dat,sha256=J15p67iXhfwwTscvbnmaYH1jxiMf8n7kvXoaYiMDgCI,608
babel/locale-data/bn_IN.dat,sha256=B4_pZdpAoXCPIa1M5PQCaAAjiXLpfArtM99CYm8JqJ0,5629
babel/locale-data/bo.dat,sha256=ymKhl17iq2z3zP5e9TAHXgRJgioHmrQrb6pwGY-OhyE,22162
babel/locale-data/bo_CN.dat,sha256=v3f48BA1za99PB5mrtwCZ1UIduBs33ehikEBdXClXWo,608
babel/locale-data/bo_IN.dat,sha256=0wt7ibuFRWOlPVaHEUBxLluTfRQVJkFX1ncqGAzkG10,1280
babel/locale-data/br.dat,sha256=GX69DEaR3Jyh4S0v5oE1809BKgLrg_FneM-MxXLL34A,319455
babel/locale-data/br_FR.dat,sha256=ioO-nP2x2c5STVkiH-RvhNxxq6giVfDejh4T-FoSjF8,626
babel/locale-data/brx.dat,sha256=KJe0Z4mjijkIvHT21ACgUPVVUEGsldy4wyq3bdWKFes,195310
babel/locale-data/brx_IN.dat,sha256=9pIIjxmY4jmGi9LDci2mDhdHADN2oD3U53pBIRNNRc4,632
babel/locale-data/bs.dat,sha256=kLtWwFkxJCn54PEkhRJ2VglpTfC0Zf44SiECiT4EiBs,264445
babel/locale-data/bs_Cyrl.dat,sha256=Xe7sB73uwd3Ayd5dqB2QMHQPhwe949S5bngxGOO8gLk,229602
babel/locale-data/bs_Cyrl_BA.dat,sha256=49_6kE_iGTwxlkieBZvxsXvVPAUrQ3hlavg2hMkUzFQ,608
babel/locale-data/bs_Latn.dat,sha256=jWzwo3YbhqMRkMWFgGPJ1SoBrHBL5OKB6yqVoJw3cKo,1957
babel/locale-data/bs_Latn_BA.dat,sha256=49_6kE_iGTwxlkieBZvxsXvVPAUrQ3hlavg2hMkUzFQ,608
babel/locale-data/ca.dat,sha256=9aV1veaooAQVkYCJNiXYQTo0aNE6AbAWdqZNh3JlpLQ,225699
babel/locale-data/ca_AD.dat,sha256=c0uaIsSk6XuXizMkzNYZcMzFcC9ItvvDTh9byxpdYV4,626
babel/locale-data/ca_ES.dat,sha256=xAbDhTv0TIq0M66QrfejjMsbIIthq2CCXMr00ojFzoA,626
babel/locale-data/ca_ES_VALENCIA.dat,sha256=6wYPEzHXDwDkvIbQhCTSMgpURt564FXRPFH59SyyXV4,3676
babel/locale-data/ca_FR.dat,sha256=bm288L4_PW-Wgb5Ty-9jcQns0i9iVy4zQY8PV3IETHE,645
babel/locale-data/ca_IT.dat,sha256=t21q_Bu_bo2FVP609O53DGAXPbAUGv5yZ-_m71S1bWU,626
babel/locale-data/ccp.dat,sha256=VT_IPjG5KpACpsTSrIrgEO89iCiFlZcd2hl_Cy-5d5w,276261
babel/locale-data/ccp_BD.dat,sha256=Lns8llZesFHOnqgmiYntJhMufHDSmzHOL-sYczkVxCs,609
babel/locale-data/ccp_IN.dat,sha256=zRmYBrG8ABv6_4YB7puTs2jsWSBBgqo0yBpvsBVHxZQ,632
babel/locale-data/ce.dat,sha256=oBZzrRCGsPkKgtlTL5tB_-J3VxclCn1GWejOU8BykyY,144875
babel/locale-data/ce_RU.dat,sha256=rAfBzB42xX9qOXWNu1kMJ278N99ohijJoWO2XAskSkc,626
babel/locale-data/ceb.dat,sha256=5_ihpr4tBeTK9cQGy8dirpQmx_PQn1Bf2fkkSBO2CWs,106353
babel/locale-data/ceb_PH.dat,sha256=nQM5vO0qo0sARNlhLIXlzxBCevhReUtYPios-RIcw8c,609
babel/locale-data/cgg.dat,sha256=fITDTLUdP6gi7b69qksuM7P0ZxoYTwaYf5_EnEIV1Pw,16091
babel/locale-data/cgg_UG.dat,sha256=87p4kuJQ3R_CLR3yPT-oMPAT9idvdPVElVxpZC5A69s,613
babel/locale-data/chr.dat,sha256=qw8DBaRubshOc5antI_7o6LbDlrrxjScPWo6SZA33qY,227648
babel/locale-data/chr_US.dat,sha256=BS6w-X9I6FuixJ2upUTEdFstYRKU7FCok38SRWahHWc,627
babel/locale-data/ckb.dat,sha256=pdz5JDJxaooNGfLSDkRp1N9srtvZV6Pgo5qgIHQ8Hqs,41867
babel/locale-data/ckb_IQ.dat,sha256=8qfAOdEjoncef0lQt6zsXiW0Nn9uY4Fb2jQMpgJSxd0,652
babel/locale-data/ckb_IR.dat,sha256=cNWVEpmuwNkAyJm8qdtOho5FEIB-UF2dOHSXoDIdWj0,1204
babel/locale-data/cs.dat,sha256=O4JuNdhyU4T-sWxWLUqBqfDKQNiGwIBpCU0YZ2z3mXQ,334042
babel/locale-data/cs_CZ.dat,sha256=IG8kxPUf2L53IheXDOJcGUHV5XPaEvrWlhznlScsZAw,626
babel/locale-data/cv.dat,sha256=igK9P_ZU-RUqXEMr0qK6B42IiYrm2f5VJw9iiCQa-e4,95542
babel/locale-data/cv_RU.dat,sha256=3BwI5TCAmMwZyudMpe7-AjZHPlK-sC0yXBLCMf3Mo7k,626
babel/locale-data/cy.dat,sha256=PHPz9CehFPlXGw3ie53NRaCg_7EfK8zZnH6J5csk5pc,350688
babel/locale-data/cy_GB.dat,sha256=ZHRJBfOpeOVn8rfsdEhIF5mY01XFhStFmTVeOmklOAk,626
babel/locale-data/da.dat,sha256=Fx85BUtIh6nw9kfcLwmarNpRprPS0gmI56tNZMcN-tk,215781
babel/locale-data/da_DK.dat,sha256=OZkvaI7AQcocAo2rtHtZq3d6-P4mzR0MWWOQ8EJXjSo,626
babel/locale-data/da_GL.dat,sha256=uyqYUJOO4nd3vn92yPsEVm6mYGXWCqSUTG4DtImKc0M,589
babel/locale-data/dav.dat,sha256=7KTLHvv2vcs90XbMfMRaFaD6jz4yj6E-3ihlc5XFonA,16160
babel/locale-data/dav_KE.dat,sha256=FP78PK3asgspsW7QIhV0jrOHFmDG4iZiGjFBvPQF-6o,609
babel/locale-data/de.dat,sha256=deFRtiKKuzjtfKs1STQoAJdTwj3HkRJ2Sh1c9J6JtdU,224823
babel/locale-data/de_AT.dat,sha256=Amo95CSd2th-U2768G7EKL5gKBXGrchNMPhrP2pS0AI,2599
babel/locale-data/de_BE.dat,sha256=cAHuCiE_b6CoIRItE8FQIpr7fR-gSsF66MtRGhU3xyk,626
babel/locale-data/de_CH.dat,sha256=XpAGxgd0jJCk4aSBdfYbvAKqRNXGQMRRuixdqkP7cxk,4210
babel/locale-data/de_DE.dat,sha256=uGWbXF2bkaVQcgna0h59yJQJctOj88om0v2NVVCJvPw,626
babel/locale-data/de_IT.dat,sha256=y1GIOM88fIEDhz5M_Seiy5sk47wTF2X5nRspsQJRWXc,1619
babel/locale-data/de_LI.dat,sha256=Gy0Iz7I3rUGzEA3ksrsiRaF3htrNIyugf8eESTuwJV8,1371
babel/locale-data/de_LU.dat,sha256=6W2M-tlU5GBY-UrVNXBp3xtWVX2IBZUQ0cj9zgpzcDM,1040
babel/locale-data/dje.dat,sha256=Ir17gIeE62TlN0w6v6mAMQqxdEqbxlA8WQEgpqegAek,16103
babel/locale-data/dje_NE.dat,sha256=YRn5qozp8AlljDhoIVdw1KfDjTwJuQSR1O6zcfh6Z54,590
babel/locale-data/doi.dat,sha256=IUjkNGqQs6I6krmdbgmYXrdmlIQcAKebSNUGGdtr4LY,24570
babel/locale-data/doi_IN.dat,sha256=Zyy44b9A8YeoCfVJjYoKgzMxkJMJ-6FCfAAgwduAXqs,632
babel/locale-data/dsb.dat,sha256=4lSQY8FHxdQPq7hCZ6V1BhYBqExasIA2517YcxcrUOE,242061
babel/locale-data/dsb_DE.dat,sha256=UEem7x_iq5-p3Tpzjtja0ONC1qtHvG2MCsQMx8KvTmo,627
babel/locale-data/dua.dat,sha256=t8qjBdqMocalXhJSPR5KH-IgaDFc42kMqQbyBf44jng,5263
babel/locale-data/dua_CM.dat,sha256=fOhCBrVImDeIe_5GZrgYvvdY70mSsENjcTEzSld5FYs,609
babel/locale-data/dyo.dat,sha256=-XNyXvVq6p6i8TflGkVT3G6uP4-IXAIyXniOcHy_2o0,10446
babel/locale-data/dyo_SN.dat,sha256=coM-rzzSZhBVSz9gchqxki0QnX4zhOD-Lk1nt6sPCxE,590
babel/locale-data/dz.dat,sha256=iAXYgyHy6pHfEK1ocK8qFbEbawwONF_VrOyHQl4eo7Q,89971
babel/locale-data/dz_BT.dat,sha256=__K3dx97Ynlcn2gcV40OXMmd-G1YchvffwSv4old74k,608
babel/locale-data/ebu.dat,sha256=bAUdnWf3QdyXegMS9prM58PIVPqHLogSWe-xXtgS8TU,16124
babel/locale-data/ebu_KE.dat,sha256=8py7zy73R_NJUahomYGMJF7at0vD_TMjbQy8AT7OgO8,609
babel/locale-data/ee.dat,sha256=aZqb3B-3-ar4852a5SPsaUCa6heiox8wUgCMFMhuRcE,147995
babel/locale-data/ee_GH.dat,sha256=B_aqQhHklFcblsk2BJmIZgwpAX17_pZENzO1Xoo1LpU,589
babel/locale-data/ee_TG.dat,sha256=MG63DGqUVcZLwabu4o_BezzGovDY8g30wKLHkrbEU8o,1141
babel/locale-data/el.dat,sha256=k9qHALvoL7iWBBicO109zlqIgWVh-I6_is_INnAFcxY,265803
babel/locale-data/el_CY.dat,sha256=07pyrGXJzOGhfxhX--19MAVJlDzuBGe1AfsnkOiHBeA,608
babel/locale-data/el_GR.dat,sha256=WqPmX-_0xIHS9A8kTDJbVCJXhqr52NEiW0CyLdGm6yo,626
babel/locale-data/en.dat,sha256=Ku1ta1HvKnj86SHnhi16K2ZsyrvU_H9tLt5imQej748,209066
babel/locale-data/en_001.dat,sha256=RQk6VeedfzPedWmYX5hzfceGsGRha4MvhdXUmRppHDI,31997
babel/locale-data/en_150.dat,sha256=fk8roPCAcfJ-j08NKndsCP1Sv5nDGnNT5K5fpMKgKrQ,1824
babel/locale-data/en_AE.dat,sha256=_fMCUB3zJ19XIagVmyZTSJd1-tYBBRftuf7NkLjV2o4,4158
babel/locale-data/en_AG.dat,sha256=AKSzhMbGCUU-P3phlu6HupABdKSEys-M96wBGbNwgBc,627
babel/locale-data/en_AI.dat,sha256=6ihO9cDogLMcSHgmWHgJDTg0OCTfEC4fVftMAbv3-zo,1179
babel/locale-data/en_AS.dat,sha256=XkSzLYRfcXzQ5S8kaps6cLh8lVLcEtpS7v5GVYJ0oxA,608
babel/locale-data/en_AT.dat,sha256=hyZWbfR6yFaN2Ck196xrxuJIPgKPQ8il0D6kJek8fNI,1267
babel/locale-data/en_AU.dat,sha256=62SK4YO8BU8VVNpLbEbozjfrzUbP25_L2l8itmUaSro,27154
babel/locale-data/en_BB.dat,sha256=qYW0ov3TXlP5U49PsDwBoGuNqydFwIDvAzb9g_PU4BQ,608
babel/locale-data/en_BE.dat,sha256=XusWtgxStVPJCvYLDwRphiW1f_irYgYqmvLT2BmgZ34,1505
babel/locale-data/en_BI.dat,sha256=FPbgGK-AHgRjz__MFHCzzOUIGhAmhx662sqL-CZWyXk,1162
babel/locale-data/en_BM.dat,sha256=xkpTQIMT4L5hhYXe9ANWZkxgyS2H6wsMdG1qtacDJH8,627
babel/locale-data/en_BS.dat,sha256=zHTFOmXUvagki_mtGdj0lht3V82InuI8-9cTPhvQ8UA,811
babel/locale-data/en_BW.dat,sha256=mkdp7htCgMvlZ5ZoXgT11mn0m7WBpH3FdELKBw7zzx8,2823
babel/locale-data/en_BZ.dat,sha256=h_ls9ROq78VZMCYsktwVXWIt90j0JHZ0jUf-k6Advhw,3038
babel/locale-data/en_CA.dat,sha256=DLGp64nnTxtP2Rtv-hCbmHWTsYocx6G2BuFLXi7AfvQ,42938
babel/locale-data/en_CC.dat,sha256=n1D9R3tb0Kbc3Umv3cS_2IfDv6gXJDkauUmLRQ85stk,1160
babel/locale-data/en_CH.dat,sha256=RaqNTYr3q0-feB3B4eDThMR_qE2W6o751NvpHEnrzBM,1824
babel/locale-data/en_CK.dat,sha256=Te6ZAYFDOE6v9domOnOXCxMrCpBSt4y8i6xxX8zplZM,1160
babel/locale-data/en_CM.dat,sha256=vogNfPzFKhhNfFR3TzWWE-P8wKdkeGujj--c757Iy-M,1410
babel/locale-data/en_CX.dat,sha256=CkFYiGUksAivYRZlmH-sfvwQ8HUgJ5Iqx1LD0UXbcCg,1160
babel/locale-data/en_CY.dat,sha256=Vl4Oa2RNsxbDmyq7cJaN9UbtK3KSvSpBQZ3ouieaDXc,608
babel/locale-data/en_DE.dat,sha256=v6hfCSEPxldGi8xgt5PDd4lQg8DI7mNHI2yTXhw1zU8,985
babel/locale-data/en_DG.dat,sha256=db0CYrcJAtcIl9MFAGUuzVUfUS4x-I0ppd4nNP_igGs,1141
babel/locale-data/en_DK.dat,sha256=09098Krto_8QdzAcWi0WRLhiMFMF0R7nT3LE8VlYJ-8,2407
babel/locale-data/en_DM.dat,sha256=d1muNBxiDWlN78TXhEJiANVe_0UxZGjJ96NoIzmPQH0,627
babel/locale-data/en_ER.dat,sha256=ZCZFGjPQWwc95TKwRCihywYh1yj-TaRmnmJqj26-dqE,860
babel/locale-data/en_FI.dat,sha256=4l_cRPoRnfznEacTx4w5wnogtzDbb-LPpVx9X8mvdRM,2339
babel/locale-data/en_FJ.dat,sha256=4dotX9Otp56WxZz2vqeHMl-FVcBKiT8BlqGktxoWKFM,645
babel/locale-data/en_FK.dat,sha256=VC91FNLl2QBhA5qkxhodFR6TWRlIus-UHJ4dzJNtebk,1183
babel/locale-data/en_FM.dat,sha256=kwQ5xP5wBGKlO-Mb2iqvsStkTC2JfMc46gBnlFTiI3M,589
babel/locale-data/en_GB.dat,sha256=Xi7wAygGZkaUTqB8t3ZMLNx8Lsw0GIyzOJ6WIRj8gko,23716
babel/locale-data/en_GD.dat,sha256=MbV-yK2BeGhQSajMlcL9TvEWWmch0zGbfBFcKj5eBzs,608
babel/locale-data/en_GG.dat,sha256=qW--gYp58HZQysSEvEs2e-PzujR6nxJw76OKtml_R9g,1246
babel/locale-data/en_GH.dat,sha256=WfV3h6HkT4PhJVSqNqIcrYOA-eWWywIMUCk6GX2DGkc,862
babel/locale-data/en_GI.dat,sha256=Pcy6njgp-RTvil94c1DoD8gPEJfDqJxSa6Ap3hz4hLQ,1201
babel/locale-data/en_GM.dat,sha256=1-9El_7BaSwYnE2NvFGES1XWvUOA3h31FOz48SyWhGw,858
babel/locale-data/en_GU.dat,sha256=Msmmrz-7nw0Mm50eo0Df8mPsJFRBBbbDtCgjNN8K4Do,688
babel/locale-data/en_GY.dat,sha256=U8FjrK6RICyHeGXrXRziQ-x5MYJv-67aiNk870rRU3U,667
babel/locale-data/en_HK.dat,sha256=h9HlVb43-lb_Apw4_0job44AR2yuA2pGB7PLD8IU9Xo,2064
babel/locale-data/en_IE.dat,sha256=owbfgGakzL-EetWiBetrHeMPXdKmMhKaAVzUoI7Hix4,2067
babel/locale-data/en_IL.dat,sha256=KmYFTJlvN4yPA1h81uPevqnBJbEMySjB6BwcgvtARKY,1397
babel/locale-data/en_IM.dat,sha256=PYHp1IMNWDea7-pfiNMq0lMSwlw6jrd1W8PijFVp_-c,1246
babel/locale-data/en_IN.dat,sha256=304vvLzb4Q-ZcDSp5AdGyi2GtaEa435iz2ZC-i-zcho,11567
babel/locale-data/en_IO.dat,sha256=KdFDEZ-ATOiBnVWa2p-QJovncI2Voygei_GH8ole4vM,1141
babel/locale-data/en_JE.dat,sha256=7Cmj2eNyJOMB2YSUAkna9CGLn9cHuAMoQedkWzTJtZ8,1246
babel/locale-data/en_JM.dat,sha256=0Iw6zJj5M1bmPLka83y-Ii5axU7oC40O2BamYcln5z0,1639
babel/locale-data/en_KE.dat,sha256=KFU4dptHt5iSqN9zSPGv5_HkLkN8tcXdMoZZlSaK3OE,1431
babel/locale-data/en_KI.dat,sha256=O13XFTeRaltrxnCjO4PA2NvM_dw-ye0xpJZeEnF0UAI,608
babel/locale-data/en_KN.dat,sha256=G3xPxRBLVKbANLsnKR7b_rFGy6gYCC4YLzRI5gT8i4Y,608
babel/locale-data/en_KY.dat,sha256=TV5QaWQr32vWrQWyBUskv1f3oq2TJVYqQPGEGJyh5lQ,792
babel/locale-data/en_LC.dat,sha256=C_KqmNUBK_9-uE4_kYbUwNIOBeO9VJ9fpLOcaWwWDjM,608
babel/locale-data/en_LR.dat,sha256=768u6chWYyWCDWWpSWkm8CFsSskf4e4-aayUrLDppFI,858
babel/locale-data/en_LS.dat,sha256=K_G56Rgw6R7d6pMU5_KfwOAUvJk_hwdZe9GqU3NNfCI,858
babel/locale-data/en_MG.dat,sha256=HA_OJPZu4eEyZP07J0MtTm8dAz4c5cXns2d5EjLArwc,1411
babel/locale-data/en_MH.dat,sha256=lWjdFRFi5Cw9EBkpRifvGV93XeQke2MudP1tv7MXV6I,1341
babel/locale-data/en_MO.dat,sha256=oal8-XgFkxo3F77Z5wKqP16pocMuo77-Ac9v6doamvY,803
babel/locale-data/en_MP.dat,sha256=4ES9-ArZ1PI5CbAQ3LLDb8sLM6LVHhAnX6KgAz0VSoQ,1322
babel/locale-data/en_MS.dat,sha256=HMWyIEh0-s1zUWHDC6XnKM8inpIDA36BSA_bN2spR0w,1160
babel/locale-data/en_MT.dat,sha256=zougfviwyZqlZHU4AVufOGZbM89TerqGW040Sr2CWbk,1963
babel/locale-data/en_MU.dat,sha256=Bq5ftR9nbRzJOacnOFQ7qluvifHCFAU81X4SsWWMHVM,1411
babel/locale-data/en_MV.dat,sha256=pi7DdFWcIr0qxBJ9AOr_2N0IihzMNSRJX79gqR7q300,2007
babel/locale-data/en_MW.dat,sha256=1-D7UAzwljnuUlgPKs2HNP0ubNQ9HGEKgIUdpkxwc4Y,859
babel/locale-data/en_MY.dat,sha256=koZHcYmaYIjYT6OANOlHdFfPuF-RmF5iyjVbkbtb1pg,689
babel/locale-data/en_NA.dat,sha256=384TeL01HX5bShF-vJgFfy5m65jRjC_SfITw9K852BI,858
babel/locale-data/en_NF.dat,sha256=rEdi2JCWTfieeeS2G0OCnKMblzSSc6NsoiEg0-JO-3c,1160
babel/locale-data/en_NG.dat,sha256=KnyRrrpnzpV97teswZmDpq3eolhm_geKohcIrryBZEA,1412
babel/locale-data/en_NL.dat,sha256=QCLHaOSc5di3zXcLcuydSPLg4mA4JV9ghfwvifq2RvM,1150
babel/locale-data/en_NR.dat,sha256=SVPL_wXvdKEYdWqUYhkRrgwOMc-f0YP1Uaznxqv4NP4,1160
babel/locale-data/en_NU.dat,sha256=0cg8LGLPIboWlBVxtmd4c10rEjqPvUUz2tyyi7kUksY,1160
babel/locale-data/en_NZ.dat,sha256=C6U6AcnLByk9BQJJ6tgyIPOFnrDlBAZbStYSQxN3to4,2259
babel/locale-data/en_PG.dat,sha256=Cq0NrSqmEseFhwCIo6noFliCfKnx3wAOenRn3VkED_Y,608
babel/locale-data/en_PH.dat,sha256=W7ezPkuNS7JqciskJ3G25Ic0SbHZTmmmmenv0a39NgI,629
babel/locale-data/en_PK.dat,sha256=UjiffoQuzoicWzGR1EK7KNTDwW5OqBRiX6Ycenlv-ug,2047
babel/locale-data/en_PN.dat,sha256=zxKpA6olu6dMYMtZpzaq35mSoMKh6AttZc6wSprPtxM,1160
babel/locale-data/en_PR.dat,sha256=GbsBjcumdJ8L-rzRYD1cXU2uzmIUYHQX4chTgkJw02Q,608
babel/locale-data/en_PW.dat,sha256=LH6T7NOgz_1iwCBhMne8ZH2hjPh-JHL2MOY3xktPyho,773
babel/locale-data/en_RW.dat,sha256=RdqSwsBE4s_LG92OJvPPTxK3BoC-qzltS8PFWM2xogQ,1411
babel/locale-data/en_SB.dat,sha256=cW7aw5w5Wos4_O_aRX1Xj4IXuEIq7eQpF50vnCEHKjw,608
babel/locale-data/en_SC.dat,sha256=uVgNnrmBfJL7Jlv_wpfDtbdk5yFjpsTeyCTBKhiSmig,1161
babel/locale-data/en_SD.dat,sha256=5JQaakikEVwEQ0YJm2AdZ2Zgg44mDPfl3ZKEatwChCI,901
babel/locale-data/en_SE.dat,sha256=docfZdy5hnfCJBQ73jZogjMfFHUdqACOMqEHUG1-pqI,1460
babel/locale-data/en_SG.dat,sha256=CU-zp0U5nRgkeyHyu3L1ls4NJJak7pmJhTBp2Osmwrw,2069
babel/locale-data/en_SH.dat,sha256=slAAeHdppQ8lHrVY8Pat5VFVwP-imbX9RbClTrFJkbE,1183
babel/locale-data/en_SI.dat,sha256=2uVRvVUDQF6M0oeKNQ-RQC3r023NBzK7jC5na6QIUfI,1004
babel/locale-data/en_SL.dat,sha256=Ht0GasacEj92hUUTsR0CL6dtcfe8beK1jsPRxyU1ILo,859
babel/locale-data/en_SS.dat,sha256=2e53Ov3bAoJClI2KxnghO_q68wsvBYm5y69cFpvZpGM,881
babel/locale-data/en_SX.dat,sha256=Ldsv42f1G7kgTFRcGdbyL_RnXUj2_whkfivt9xCS9oQ,1163
babel/locale-data/en_SZ.dat,sha256=qidm3zACYSmI6TgdvkJ-URbDk7BdHg1JmENh3jFUsm8,858
babel/locale-data/en_TC.dat,sha256=BqCmasVKStg1Mia681u6ZqtglR5TxC0QgCD2j1XqAwM,589
babel/locale-data/en_TK.dat,sha256=KmgyiXJLdOlswDEemXHOLEuZb5de5ZM0YmdDxNnAHog,1160
babel/locale-data/en_TO.dat,sha256=wOZyazP1wVbQhv9Y_H_NDHb0ldHsMPdZPN8O-O1c5ZE,609
babel/locale-data/en_TT.dat,sha256=UwplYXlbOs4hLPyDovdYDv6yz8KGChSZ6ufJ5htjfQo,627
babel/locale-data/en_TV.dat,sha256=Z_vPwZ0HZB4aDDibrbzesmYFzgKRqk22hS2ZKqhq3_E,1160
babel/locale-data/en_TZ.dat,sha256=syqDYFfemhw375IYXAM-F03S4gxAe7EbaJcYVbjt834,1412
babel/locale-data/en_UG.dat,sha256=yczBoonl1zmDZpeNyAHAKvQ_OArvhP7AWVLOtKv9Jkg,1435
babel/locale-data/en_UM.dat,sha256=QpePixV3RZ9RiqrYuz49bkN6Xeg-UG2y0Po_yaLbSOQ,626
babel/locale-data/en_US.dat,sha256=JU7XRlKyRBNlDNbGDabuIBWP_tfuFahFBUNDL16cE8I,626
babel/locale-data/en_US_POSIX.dat,sha256=3T9hB0xi9COJVMG08Gn8JRFDB2xaJYUZdUxZiOsSfT4,1279
babel/locale-data/en_VC.dat,sha256=udrNbZKYSjk5vRAlIMd_k7255C5GUjBmQjOVm_GSshk,608
babel/locale-data/en_VG.dat,sha256=_MFcYRjyNuFMVYGYjGBQMC3C2_IZjcSXGLxNFUt15z4,589
babel/locale-data/en_VI.dat,sha256=ptodXPLBh9jA4d91bhhHarqlw8t0BuiigzyLPxAX3Vw,626
babel/locale-data/en_VU.dat,sha256=OKNpgxA_p9zCpKhmDA-r2qAUHQmeEY-ITSvz6Hqlp8U,609
babel/locale-data/en_WS.dat,sha256=_qLMqdSB0O18FukP062U6fiMk7uFaNUp-u8qjJXB3SU,629
babel/locale-data/en_ZA.dat,sha256=pIlHaobS4oS2vrpUqX84ptZzB98_-6LJKLdcuBGsREU,3357
babel/locale-data/en_ZM.dat,sha256=Zphtlz3AeWJ4xZaeDtX29_xuSN-aHrmFX8-dg4j9ePs,858
babel/locale-data/en_ZW.dat,sha256=iPD_f0a9qZUtw6q7NIn1c-oa3PpceNPqkYXIrLG1MCE,3287
babel/locale-data/eo.dat,sha256=nN0mC2tqMGHjHgcUK_Q-SafOvoWt7H56AUI-elQLH94,81019
babel/locale-data/eo_001.dat,sha256=Mlc_rMI2tpO1RL6ZJcuMDcO5ou3NuFOxZ16TomDvwrs,823
babel/locale-data/es.dat,sha256=8McfO7LKmKIBdKTzL-MeM2lP0pn0b7sMtsuhbIGsYFY,224732
babel/locale-data/es_419.dat,sha256=pq16b4mIbH9xbOJsUV4X4eWn9FXabnX3AtL9aTiHN6s,30118
babel/locale-data/es_AR.dat,sha256=7tpaCeiL8CUk3O5esNsLti8FOwhHuCAElQ27HUWpvcA,7886
babel/locale-data/es_BO.dat,sha256=MvLKTzGXdAud9NcEr8vDat2gEsoD_IhZT8xKGawQbgo,1591
babel/locale-data/es_BR.dat,sha256=CQBretr3RreqaOiCUo5-cmR3EIlSUiQVJMd_fhPktIw,628
babel/locale-data/es_BZ.dat,sha256=whnvRybQayDyZH7OFfVQHMR3aHYLZhpDU2gY-j_PbYo,627
babel/locale-data/es_CL.dat,sha256=8GpTGhxJG1Tq_8Ayj-_jUOqBpc06lvkYEP5KQzQH9UM,4997
babel/locale-data/es_CO.dat,sha256=8GhX6FjBsC2PtUnBtdoTegrXphcoXs7jJkY3-LiyrH8,8118
babel/locale-data/es_CR.dat,sha256=ZCVLrW4dvJ7oFoEsKJ-tBB83N3BEt7LxBgfBlzSwbTk,1215
babel/locale-data/es_CU.dat,sha256=hjouuq52dJG7NJR3ypl_nAHpBIOYgV88AYWnR_i0378,629
babel/locale-data/es_DO.dat,sha256=XVPP4NQZUKUHcuGstWQrOkDSUfTUBanYTX9IVMAewYo,3482
babel/locale-data/es_EA.dat,sha256=vYi5_0kkB6gIqCXTdtHnD755-gzO2y_Gd-lAy8ahpMU,589
babel/locale-data/es_EC.dat,sha256=LuVX8W_iHGuvulTuhrspFwwv5oHyFuwCQdVFeDSuQAQ,3055
babel/locale-data/es_ES.dat,sha256=VCWxAz9w1EHetI06vwya_gkk7vDXGGSXJumViKKb4Ww,626
babel/locale-data/es_GQ.dat,sha256=UN8mrsv6CDtZ3TBbiTwHFjn5YJndJjBwxugkV2R6f5A,611
babel/locale-data/es_GT.dat,sha256=b2I6WKIGggyIJDVIxxDo-Redfk6oKToDlM3RRRboZ2c,4328
babel/locale-data/es_HN.dat,sha256=CFMSWzpHonAw0KPpY8d6LpuH2Ly1qGXeltukAMzxV9s,3180
babel/locale-data/es_IC.dat,sha256=ap4rHt9hZKqaWzlIZXgs92V3EWTmkCULMIY6Hf91T3k,589
babel/locale-data/es_MX.dat,sha256=c7IVejAgTPtva5R6_bdzjF3K8KotHLnEVVi3ZkaUKuY,27815
babel/locale-data/es_NI.dat,sha256=SbZU4zW1Xz7KfOvSq0MJS-GjIRzhl3WPfkCDzFYP1u8,1149
babel/locale-data/es_PA.dat,sha256=Ohd58JsytquJA2FjjjnOIF3i0aOrHGclXaK4-ZOMDW0,3458
babel/locale-data/es_PE.dat,sha256=s7M0cD37QEH9_xb2C-JkYWTaqBEcygrB_pHvTyd11pI,7373
babel/locale-data/es_PH.dat,sha256=ryJn617ZvA3964dxe-8WFokgsPuQKJ-Q1MbwCLQ3Fko,1221
babel/locale-data/es_PR.dat,sha256=jHtw_t9PRmNTx1l7RFOEzgQb2hJrVeZ1Tmypz_vCjRc,3485
babel/locale-data/es_PY.dat,sha256=3OXI7u6yhD5lKPDQ4mtxQ5I_OxKoo2hSGm-hnShSZo8,5166
babel/locale-data/es_SV.dat,sha256=fOOFFYdt6LIsNyJgLOEQdrXBTSfO11ThqwxApRh69wA,898
babel/locale-data/es_US.dat,sha256=GQD4psFDJ0bT0lnLHL1j_MscWUpcjVVD3kDHAgCuFFk,22889
babel/locale-data/es_UY.dat,sha256=Du8233PA5mP2YEWl4Uo8GJ9apn8B3Dq3uo55PlCiJFE,2296
babel/locale-data/es_VE.dat,sha256=wYZBd5KzgOYLDllnsY9-KNnIDnaoYtdqASngkQaMKlA,3374
babel/locale-data/et.dat,sha256=BszlxIJNQnW-a2GsRKobkvMle3FW1LhC_A8haj0EHyg,216816
babel/locale-data/et_EE.dat,sha256=xpoZTzSn447SsQklqYnKUUL27DkZuNsRpQxTn87Tmlc,626
babel/locale-data/eu.dat,sha256=P3i8oD_02OsG0I9KSF746XwZxb6Emiy95O1XttiCYJk,225920
babel/locale-data/eu_ES.dat,sha256=xvTtCQUjEml-wPLAZR4kU_hhXZ-j5oIE5MO577tCdFg,626
babel/locale-data/ewo.dat,sha256=-oR8kJvVwheYPNc7LXH5hMhEXaDe4ASrSODejMqIHnw,17500
babel/locale-data/ewo_CM.dat,sha256=NirWcwhJ0SSdkIex0afT1IDuwyfJBBcfX7CGnJNIOAQ,609
babel/locale-data/fa.dat,sha256=-cHPI7Wstw2G3kgQujgmVfi7rTdbwx7JDQ5jSniCcEM,239171
babel/locale-data/fa_AF.dat,sha256=vVhetVdKmJLaO2TyMFN9QouU7RjT-j67WW1uu8DofAM,10670
babel/locale-data/fa_IR.dat,sha256=ZnDClkeVc1IPiEGa63b7BhvnhklUhgige3sTjeEK6mU,651
babel/locale-data/ff.dat,sha256=C9rRpGv49-pQvMvEOv3z4rvFawRCwh1Un86SyJjsJ1Y,15939
babel/locale-data/ff_Adlm.dat,sha256=aOK1Uh79a-jukzF39iZbT9VE9I_Kx1yaWlX3hD4DfAk,341327
babel/locale-data/ff_Adlm_BF.dat,sha256=7b8PdK1LA0V-odNH3iwuNDDR1vQYQhXvHp-5bB5ZwLc,610
babel/locale-data/ff_Adlm_CM.dat,sha256=32kFf1KDw82I2SKzaVB4P8dBfmkw_mmG6fYAuThS99g,629
babel/locale-data/ff_Adlm_GH.dat,sha256=90UIh5AUwO8eqvY2d7MzCmPwJ2XNFfAMfHqqEr-QZio,1209
babel/locale-data/ff_Adlm_GM.dat,sha256=NqlOMO7KDanw-Z-dnG4jSX1SUESFQrNG1MVCMutQs0w,1205
babel/locale-data/ff_Adlm_GN.dat,sha256=VAK9og8mz1WVXD9RnykNOiKkC69nIF_gGgkwKensMX0,589
babel/locale-data/ff_Adlm_GW.dat,sha256=_BVL7y6irTvBSRhVMmICwv4uNllP5nxIqPGpU5i9sCs,610
babel/locale-data/ff_Adlm_LR.dat,sha256=UYThYdKlKFe4XX52x7WO2xmkiHA9heV9E3K2Mg0RP6o,1205
babel/locale-data/ff_Adlm_MR.dat,sha256=anYa5CmU8BiiYRz2nL12UDCwLJIsUIbZqajTFSYmvd8,1206
babel/locale-data/ff_Adlm_NE.dat,sha256=EmZR_KWVdW7b5TxkRsivHLoYKwHU029v-R0k7zieWQs,610
babel/locale-data/ff_Adlm_NG.dat,sha256=OLPxRiTM2InmMtH2gCRJRhbmwhawtdSR--6001ckT5k,631
babel/locale-data/ff_Adlm_SL.dat,sha256=jNon1Gyb2bs6PNMY_ZhbvyA9BbmYk-7kpNCc7NebXmQ,1206
babel/locale-data/ff_Adlm_SN.dat,sha256=9USLkiIrnIVKikQHcPqyF0bwUqc4OiAm9vDisk9boyA,610
babel/locale-data/ff_Latn.dat,sha256=byAYS1KDI0NXZf0r5uEtjiW_dvH3S7nniynJX6jR30w,839
babel/locale-data/ff_Latn_BF.dat,sha256=NNCmS9PhIhnRzZlE6Zn7Sjt560T_zY0oAGvs-wkJQjo,589
babel/locale-data/ff_Latn_CM.dat,sha256=-vhCSM41OmNfJwpW2ArLlVSOBAmbxI4qkdGrOuG7jxw,608
babel/locale-data/ff_Latn_GH.dat,sha256=OHvS5DG_Aw2lEabjE90vUXuwgumYdSdrkYU4Wz0btBE,1204
babel/locale-data/ff_Latn_GM.dat,sha256=ISo3BU3QNGC0jjjNlgj9lfpPBE-RKcRzpWCn4Wg7Fww,1200
babel/locale-data/ff_Latn_GN.dat,sha256=cdoXME19UJX1H7WkepaiJEiUql4zOY7h5uO8GKQoZ_4,609
babel/locale-data/ff_Latn_GW.dat,sha256=lIrg2frFHCvM8guhuR5OmGU9Np_yUTIcORKQITZSFYs,589
babel/locale-data/ff_Latn_LR.dat,sha256=zVPtbYZtNSl8KdW1edv19BmcMyyJ2hBA4_toOMo9xG8,1200
babel/locale-data/ff_Latn_MR.dat,sha256=_BulUSi5RdFwiQLaD_FEaEYqfKfzVlbI2nZkyW4sUB4,1201
babel/locale-data/ff_Latn_NE.dat,sha256=vYqMUR9LCykf0H_rTE_oeS9fYK7t-ajKpbK1IpF9-Cs,589
babel/locale-data/ff_Latn_NG.dat,sha256=NAMpFyNWE3dSzIwJTRBwH2SUhoJlu_AzinAtCByfyJA,610
babel/locale-data/ff_Latn_SL.dat,sha256=woELh-cKB4x9tq1mCRPltLRXK1B5fGYLHh2Dbj_bobA,1201
babel/locale-data/ff_Latn_SN.dat,sha256=Idf9JfDjAfWlKouD9gYB6m6_qg9P9xUIRAgMQ5O1-Lg,589
babel/locale-data/fi.dat,sha256=43Kk5Z-cv48HWbdRDlmD2TVn_m4GtBilfdrdBfLDJlA,245604
babel/locale-data/fi_FI.dat,sha256=CqHzlsNe9s14gZWMaUn9abl4FmLAZknXRX1lP5Pdrc4,626
babel/locale-data/fil.dat,sha256=ish7molhaPNx6bPmOkOOBkph2DrC1k9dTrxb9lWdrbM,196499
babel/locale-data/fil_PH.dat,sha256=U-tLxLn0lDKKpUqEQPLTumOuJOIYi80HvPnUk2SsObY,609
babel/locale-data/fo.dat,sha256=XckcnBRK6rSrr-6fCez6GptD0TtRuU7EIWBGpNH4oBM,177605
babel/locale-data/fo_DK.dat,sha256=V7Kq03gQkns2EDztSyIiRLr80EtZsGZnmoYPsChW__w,647
babel/locale-data/fo_FO.dat,sha256=WZJB7n6uQpGsPNWVXqP851OGZd5RmfSMbQ-s_C-00tQ,626
babel/locale-data/fr.dat,sha256=uG8T3IWNP6SqIrArWZwOPobbEKyqmW5F4gOOD32Lzu0,242797
babel/locale-data/fr_BE.dat,sha256=LBm5IHqOkcci5mfpTBX353G1loIeGSLvM2cNeTf-Rng,1231
babel/locale-data/fr_BF.dat,sha256=gVdej2f-lrFMVDjQNCma1-odtbYzezlFw8YR16ZuMas,589
babel/locale-data/fr_BI.dat,sha256=hCmnp8GizMpXqkYPSnRFUMb1ltL9xT1aIHUOt8uzR5s,610
babel/locale-data/fr_BJ.dat,sha256=CZgeRt0F7zcnCbuwouXBxTg1Ht6M4UpS1JYNgdnGZOk,589
babel/locale-data/fr_BL.dat,sha256=mN3e240_oM-t97i3jZ33ptBFR3XJFtq2519QXQskeDw,589
babel/locale-data/fr_CA.dat,sha256=T6QtCKCDUWkPL3VVDBWXJY6iL24AzQEFEXHY2566rLw,73881
babel/locale-data/fr_CD.dat,sha256=FJeps7nH-v54zvLTXGD2GjY59aPL-SAjuS_FN3s_VaE,1110
babel/locale-data/fr_CF.dat,sha256=zElh_1aCiSapkL83eytl19hKu0R6lrE3xmb_a2lf_cM,589
babel/locale-data/fr_CG.dat,sha256=XqZxi9XodrhYnQqagiCv8zc51Aqv8S_E3AKgZxPO6QA,589
babel/locale-data/fr_CH.dat,sha256=-eaI2eEPrdDqP6s-QxgPYyZzDBr6dXdVXdcrt73K9Yw,3051
babel/locale-data/fr_CI.dat,sha256=PULA-d30mWwNN2Zsg_58tbUde8ljeA7ej6_bQSvyngM,589
babel/locale-data/fr_CM.dat,sha256=IVe0VpFrYWMJui4JKST-vNgRuRn936x0Ex01OdFNN_I,2123
babel/locale-data/fr_DJ.dat,sha256=wDFvv4kt4rW0Yl1loIrVt5AO8kZ8zRvt-sQK4sOiNDA,1221
babel/locale-data/fr_DZ.dat,sha256=y4uEnNW4XHE1DOLEuvBcDIgs2ei40TI7N4GOEOfThAU,1263
babel/locale-data/fr_FR.dat,sha256=oucSQVTi8gnvWNQ07WJPnYh1YQRxbYR6afhy8Wd2YgI,626
babel/locale-data/fr_GA.dat,sha256=hjGGeVpmPCTxP7LEMxE_iUUS-uSfRnY3unJ-800ilGk,589
babel/locale-data/fr_GF.dat,sha256=FwIBhmnYvA-VIAgc_n9JLiENGTZMXFANqyFFpeNjNYc,692
babel/locale-data/fr_GN.dat,sha256=BIJ_Gl1Yp5fVwQNISO_f4o5U3vgOWPKB-4UWMjp_SMw,609
babel/locale-data/fr_GP.dat,sha256=7IjXNU_xYD73C0EaZ2IWMxZ8kzIFRLWgrE07-xHFB8s,626
babel/locale-data/fr_GQ.dat,sha256=zMNFOsgv_5JFDvnqB6AovINlxEdr_QYBGw2Rl6LsdGM,589
babel/locale-data/fr_HT.dat,sha256=FIn4weL4_b_phmnIIQFDdwhqY3UFaLITSGKAZh_sIJw,1873
babel/locale-data/fr_KM.dat,sha256=SaUGzyArQSXa_pwsb9hw0_fs1TjcZq7o2CFW1mAfvQk,609
babel/locale-data/fr_LU.dat,sha256=OZ6lHBdT7fHpiMgMaIEJhNB4ohZVMZRQiJQT98n2gLE,687
babel/locale-data/fr_MA.dat,sha256=7-FeaIFIZGfbunjR-M-lTr0WkTGljmC354Iadk3_S-I,1277
babel/locale-data/fr_MC.dat,sha256=se81gvlIKgey2DgfCYayuXiwV0Wykw-QM4otwduegCQ,626
babel/locale-data/fr_MF.dat,sha256=asOP0aSNk9sx2Jx3R5QigjvOQmgEzRP0atpznWTZEII,589
babel/locale-data/fr_MG.dat,sha256=GL58hdcr_DZePturTSmv-8WScEg60WajuKuijeBs5hQ,609
babel/locale-data/fr_ML.dat,sha256=x_UkTI0saDvoYCiYdNF9CWoyc1VvMAQFBw8APjCEL78,1126
babel/locale-data/fr_MQ.dat,sha256=v3tmYxQ45BkuVen2er9vMsxTceL196E98XYPsGWKXTM,626
babel/locale-data/fr_MR.dat,sha256=BuD223TXTxBhBpwF98NgIUhXPmH5-t5fajBIsfrMV3g,1201
babel/locale-data/fr_MU.dat,sha256=UVc2y4RDe6Jy6_48f043AXBUqWLvktTjnj2osTeAJO0,609
babel/locale-data/fr_NC.dat,sha256=Liy4q5CQx43KEep69njgxfUENHEJRfXaZJlsK_UcIbw,589
babel/locale-data/fr_NE.dat,sha256=beqoAaHiYhcvUeABHOBD_9cJQ01DQzo5nbAZb5JZb88,589
babel/locale-data/fr_PF.dat,sha256=mSlv8dzrvNyo9XfC8yczKIKGaEPGTIpf71Oi1IH_f78,589
babel/locale-data/fr_PM.dat,sha256=yukgtaee7ROFoFHM7dUO9CSYlCmipm1i5ZEIsbvvP0o,589
babel/locale-data/fr_RE.dat,sha256=IN73Uw9cZdifS4rK4SfWiecLcAX0R2F4j1aV_DusCUQ,1142
babel/locale-data/fr_RW.dat,sha256=b6cY_0EAjkJjlLAjdYr7o8vkdzB0sQbIgwgWsFlaO1M,609
babel/locale-data/fr_SC.dat,sha256=ejzZtxh5_XDx1B0oZFQx7oDpuuxAsmNp1mYxGtnRs34,609
babel/locale-data/fr_SN.dat,sha256=AzbXwg-QV0b_-M08HrFFVoi0CvQSW9tK-rNHQ-N-9d0,1277
babel/locale-data/fr_SY.dat,sha256=0lhdk0QpQP2rwNOr_vfqUPQ-RbIXObSKTQUHqyaOyHA,1263
babel/locale-data/fr_TD.dat,sha256=vuR_78aSnpVv6V7XSzuTrpJspe0lVWkGsQM1CrAYFl4,1181
babel/locale-data/fr_TG.dat,sha256=GWo6BaOsi8-YZfuWYIEDMyodmtktbkK54R3fNEwvsNY,589
babel/locale-data/fr_TN.dat,sha256=yNRxllFu4l3gX9bofg_BTz9QnLUNCMR2EL4ifPnqJCs,1201
babel/locale-data/fr_VU.dat,sha256=FqFb4WMK4F_owTRQZXo2vlxVgi7MCG1kVz8-nPcdvCk,1201
babel/locale-data/fr_WF.dat,sha256=_LOp9Pd-uVPzUqTOLmdKAVmqdhJSc9TQxN-q0AvFZMA,589
babel/locale-data/fr_YT.dat,sha256=M-OawlEGCEqzxMFehDb_3Ofb76HA6nwXEBFBKEi4qMw,589
babel/locale-data/frr.dat,sha256=L-fFl4d5BnemqGyEyW10bj3SAgPepLQZROr2IJCx8MI,53110
babel/locale-data/frr_DE.dat,sha256=eXOAS-NGJzTZHNQWy0SiL3nFhcYG6G8UUSIiVaN_Wkg,627
babel/locale-data/fur.dat,sha256=ibTcF2aLtp9IYYjCQEY_7bL8lKi_paYG7ZdwbWlcwbI,34861
babel/locale-data/fur_IT.dat,sha256=-jYgvCMGoV9qmo1lNuPbfFhw2RiwM9-XrMAaisqk3ck,627
babel/locale-data/fy.dat,sha256=o0iJeYZojO93W_NuO0gmxxerMEGuF0bIuFYQ4g4ppP8,111284
babel/locale-data/fy_NL.dat,sha256=6kDdfEWgZuA0BeiB9BM8qhtPVPqUB4zBkpQBmEulOpU,626
babel/locale-data/ga.dat,sha256=bnr_JdhSfUugqsDtJKUgl1llB3ApG00yk7_r_0SM90c,344177
babel/locale-data/ga_GB.dat,sha256=DVKT5Ub0mvXWADwJua35XUCwxPrRj8olUR-xGv9x07A,626
babel/locale-data/ga_IE.dat,sha256=cCW_n5mlSTNu6JzFj5bZMiJbEXFiOHH8BrCB4MnAi5Y,626
babel/locale-data/gd.dat,sha256=d7E78NlA0YK0CPLMH3ZEeqxzQum6QTChnR7KwquqOtU,326085
babel/locale-data/gd_GB.dat,sha256=6VHHQkNfDnsLrshZ5VM0AvbuOmAkVWFf6KIBK6dXxhk,626
babel/locale-data/gl.dat,sha256=3IsUJeggybPDaWhA7YcY16irA39_L1pbtlKQwrHEou4,194805
babel/locale-data/gl_ES.dat,sha256=taQiFoK4jse9XR19xt95xT_BXnzftMPMJgKk_ZIh1xg,626
babel/locale-data/gsw.dat,sha256=hbEKVfQie_j4mD6y64YuoUaXviseHItAzvRkgzuOPnY,114204
babel/locale-data/gsw_CH.dat,sha256=oNDsu5FZKmaMx0q94MsggWUHYobgGv6lNNwqRbm6mes,627
babel/locale-data/gsw_FR.dat,sha256=4rf2w5Q1j3qezQ5Jf1-0qkY3K2Yk-ArQBBFCciWNfiU,627
babel/locale-data/gsw_LI.dat,sha256=4aFdXjXWs0W3IE-cqe06PKFdB1l1MbQre8NY2sm3lWM,627
babel/locale-data/gu.dat,sha256=ilqOtgibw-ewFITrEMlfSRXWBqpGCZj90Mu59RSZ6P0,265509
babel/locale-data/gu_IN.dat,sha256=4mup-pKABihWun3Ougbz8HiGoXtPDPdAqAKMBma7Gvg,631
babel/locale-data/guz.dat,sha256=cKJkMRMPh1_sc77izOmIha8KHGsJpHPuarv4Wukep_U,15897
babel/locale-data/guz_KE.dat,sha256=S-xrYnojrbkIXv_AMMaLR-0Et8CtW6Ty3FDkikLYqS0,609
babel/locale-data/gv.dat,sha256=jFC4dXw2wePKj2yU-juFCuZhXVA2yA0FKIFwE4Bv_XQ,4002
babel/locale-data/gv_IM.dat,sha256=32eF8Qm1U-NzDs6CsC1a5G40zereETci2vy066Dq9m8,607
babel/locale-data/ha.dat,sha256=b9EgsNapAmD91etX4AC20LVkcu10R4VAHSwcbD3_6GA,159445
babel/locale-data/ha_GH.dat,sha256=m3n1M3hBHEFA7PWp4pgBL5ApXFo3gKTtwZCNI0m9wQU,1204
babel/locale-data/ha_NE.dat,sha256=zijJbxFCkxERAF9QsF4GBCgaTdOa8yFdZWRAXeGL9l8,650
babel/locale-data/ha_NG.dat,sha256=7ArPguvlMmsMd_KuhyAy5K0PTuvdzDgbCrmY5c3hyKk,589
babel/locale-data/haw.dat,sha256=m49GeegEywvHhYURQ5QRzVQMOrfHKeLTh7EAjPKeMi8,16232
babel/locale-data/haw_US.dat,sha256=0npKxik41EG4w134GeOKBCqQiyn4W_4RU9Xol9An9vI,627
babel/locale-data/he.dat,sha256=nVny6iyoRSedk-rWDv3WsR3FeimwUst7a2-mqUVxckY,303440
babel/locale-data/he_IL.dat,sha256=tv1zu6LbE2qFr5KkxegGM6sl5YjsHeOohznihTWqul4,651
babel/locale-data/hi.dat,sha256=FwFKKGdlxmBTeo6fcRDq11Nsj9RwUDPuJYZh6wV13nc,268757
babel/locale-data/hi_IN.dat,sha256=laF8SEGi7j2jIwdbvx9jumoN_ZSlsmM2qct5Qpdzy8g,631
babel/locale-data/hi_Latn.dat,sha256=3MUJQMFXdeQ0ZHvht3c0U4bKL3qc1qkh1uraQGqHtSg,65752
babel/locale-data/hi_Latn_IN.dat,sha256=laF8SEGi7j2jIwdbvx9jumoN_ZSlsmM2qct5Qpdzy8g,631
babel/locale-data/hr.dat,sha256=0zORkbJj5gGBAfwd53E-rvlPc_3-AMveVdChaBGpCbQ,267997
babel/locale-data/hr_BA.dat,sha256=cb0WcMYeSmL0iyadbeYGokENF3IdPgPG8Ir3pt2QWhI,1161
babel/locale-data/hr_HR.dat,sha256=FBTFejY7tzVjCu1TCX5PtUIXfhL2iN0DukagJf7dS6E,608
babel/locale-data/hsb.dat,sha256=jb2WlatOM5PwAlF79WeTyZxG38uiQQd75ftat7sZH-c,243022
babel/locale-data/hsb_DE.dat,sha256=mJpofwRoSQoD4uMNdi0xcLP0qyq0IysbE2VkXNYniug,627
babel/locale-data/hu.dat,sha256=mzeRPjbgtx-DoRmvdYGBydXCkImbSc727nRMmeB7nRQ,208704
babel/locale-data/hu_HU.dat,sha256=KndrzgNop55GlUso27Dfpf6rW3RA7YhQibwBFTzufk4,626
babel/locale-data/hy.dat,sha256=EnUNy3EtdR_hFrpgVvDth9pKLU3jhKOdFCXKpn4D9-o,234410
babel/locale-data/hy_AM.dat,sha256=4HM865GP-TvuBp3XjB41rgc1QuXLLITSt3skVtB0QHA,608
babel/locale-data/ia.dat,sha256=YEE3AMyIo0MlZwcMgrrTEzzai8tuO4mCWXl3BrNzpww,130549
babel/locale-data/ia_001.dat,sha256=onWUTi-JeTzCyFGYj9VWyvYFnE-0w59rnsDeP3WZfCY,914
babel/locale-data/id.dat,sha256=pM-HpFK1hqoCo1bShRw5viSgyowNLRs6n7MwAMlUK7Q,178649
babel/locale-data/id_ID.dat,sha256=Q10Fz7etpCtqpGmEOzhzIAluNUViuPV6fJ8Ibp4TMDw,608
babel/locale-data/ig.dat,sha256=3h4n0j_P7SGNC8pmB56qJzmH0FKvcEJYbxunerKtCqA,70575
babel/locale-data/ig_NG.dat,sha256=qvl7ZtJLFgRf6Jbys3rPutuwKL0nImrLIyI2KxDJNMY,589
babel/locale-data/ii.dat,sha256=LyrWW1A4eexiKIzLJo_ggvpaNmKw6Ufvc450a8X0bOs,12360
babel/locale-data/ii_CN.dat,sha256=ff5vAOGO3nXzWVe_sQ6UFG6IdsuKvcWnOO8a9N8kMjc,608
babel/locale-data/is.dat,sha256=NGvnffF5_8ysFKNc5ej9_VsuXgE85gLKdOPsbq8ET60,204210
babel/locale-data/is_IS.dat,sha256=vkGTcivdc7UMK2uv1QCKnJkoGh1cFUyK877xmLKNWfQ,626
babel/locale-data/it.dat,sha256=FE4DY2x0VHN9VTs3P9ppAQoqBj75zTFQFtj9KPBDDuE,212807
babel/locale-data/it_CH.dat,sha256=5BStfpslfbxhW1tUWJwoZqRWxnmIFwhbvbOd7gEowQw,2900
babel/locale-data/it_IT.dat,sha256=EPq-ZuC7fD9sVQNf7K7dGReI7pvxix55SFteRJlEheo,626
babel/locale-data/it_SM.dat,sha256=gpwEWv5kVspUSBElJAoge82X76LK1lsgxShdk_BdxwY,626
babel/locale-data/it_VA.dat,sha256=drgEDlw3k2saTMXzEz5-BkkHgCCdnXVQ-aiCHUMYAUk,626
babel/locale-data/ja.dat,sha256=oJRS9TqalgGuTUH0U9n63SUlP6FUGOYdC_N2EXPWTnM,218722
babel/locale-data/ja_JP.dat,sha256=fqV-tzCjVKeIhB1TH9R2vsz_kpEwD2KSdYUMOL2zVQY,608
babel/locale-data/jgo.dat,sha256=_zVzqLqDWLnfdMevsp7nWExcOv2uC407_Ef37erPiRY,12547
babel/locale-data/jgo_CM.dat,sha256=4EKGSIDydn6xezIwTpMhOZFnheOhhMWfwadqa9rRRpg,609
babel/locale-data/jmc.dat,sha256=ym6X0J7f9pbBGaQHy0WU1cSorAtb54u1-htfim-SACs,15925
babel/locale-data/jmc_TZ.dat,sha256=bpvlP-1bAXEnvIRsPxFHel5X-8eLxF8dUOlkJctN78k,590
babel/locale-data/jv.dat,sha256=6acsLAIIH6lS5wGR3U1Z2PASU4jDTDr2nyZxZQUcAto,144365
babel/locale-data/jv_ID.dat,sha256=H5wi4GL8eID9c2QUxpz6qpFn5ORgdpE2mjYxdkozJiQ,608
babel/locale-data/ka.dat,sha256=9ZV1jIfO9SiUVEvPh92T_CHmP5xcUFwTkeLUPoCNWtE,282815
babel/locale-data/ka_GE.dat,sha256=4G3wWIQOIZM5Z8r1Px0d4DvTOMwbR4Ubvq4expe_gY0,608
babel/locale-data/kab.dat,sha256=lfN6hMjJdj-DGbGh_LxkY6rNFZbVJjJAi1-xGDHenQM,149013
babel/locale-data/kab_DZ.dat,sha256=KbrMqfLO_TlWJlCQVmK5IjqCwVppZUryATx2Rq5YTaE,652
babel/locale-data/kam.dat,sha256=WR8xJ9VZM4_i-ZYA9ZpNnnCiihUBt4Jc73SuJUkgZ_I,16062
babel/locale-data/kam_KE.dat,sha256=vfQX-o-otm5WDwv2qrHY1lesX-AQ9cX_2HW-nO820AM,609
babel/locale-data/kde.dat,sha256=gxDvjwKX05VCkFWccDFjMNcPLHklCbXw_QiX5SQKNuc,16356
babel/locale-data/kde_TZ.dat,sha256=RdJ-ovdj55xBfaOc5mE41fqsNdLN_7oSIOcyq7-aApQ,590
babel/locale-data/kea.dat,sha256=5hwDXs0QktU_8mjVbAqmq5S4eJEiMA9_m73AJcm2SG8,93203
babel/locale-data/kea_CV.dat,sha256=7lbONkE-y9_doiZJxjyGYM50Yz41JNGwy7dV53vvhEs,590
babel/locale-data/kgp.dat,sha256=-Gcg3Bs-bhQC45xbIjpKZAYcYXcq-ICQZRqy3s3y5B0,205354
babel/locale-data/kgp_BR.dat,sha256=NsDwIsxDSpoycbHq2HT-Jhm8U0noCil_djiRgkRq8PQ,609
babel/locale-data/khq.dat,sha256=c_oUgiCiIPtj2I4De3hh9-EhA3Wss2hKuEVR20-CuO4,15798
babel/locale-data/khq_ML.dat,sha256=CbrIcKwmxw5THhW-nZ-sPFZjsfgpHZUDl-hhWH2toDQ,590
babel/locale-data/ki.dat,sha256=PYFljnakBn7Yci8KdInk9qAc3-qrnikxyRXM1a2-faA,16004
babel/locale-data/ki_KE.dat,sha256=-fcVNnw6zrxr3Bw7mi-vpkzP0v4v9t2hkj5ZEuG_5Zw,608
babel/locale-data/kk.dat,sha256=ibQ3Fwu6c9U9adiFgeK1Kl2aXDsDACzlrK8sH5QmGsY,242811
babel/locale-data/kk_KZ.dat,sha256=DhjfmmZRmr-w8q98Mqr8h_v2hosJAjTtTFo53E3QGQY,608
babel/locale-data/kkj.dat,sha256=TvP2s91CJUYsGkKUJGMRvVmnYUrHBopGB86H87wJlAQ,4562
babel/locale-data/kkj_CM.dat,sha256=KY8LZH7ZqifH7BTxFz4ylu4d1LAAxMAD8W-a0gYsjZo,609
babel/locale-data/kl.dat,sha256=oIqDGEQ9ooEnsEmHKdh3MdqC8BGYj8havko6psn_25Y,59291
babel/locale-data/kl_GL.dat,sha256=RojeiBiofKUHvk9f_ITt44uxy9gGhxz-sVy6sBn4Zcg,589
babel/locale-data/kln.dat,sha256=QgSWBrUUgzdMjMp3ue0VV68QbOSFnI_Yl8g9L69XBQI,17890
babel/locale-data/kln_KE.dat,sha256=RydM7LQVL9u4kqeFACUbNwf4M8vQQhP0qkKM_oL2oGM,609
babel/locale-data/km.dat,sha256=-g5I1K7BVtOsOlA1_IEB0RDdJ2PHcbcomfu6sgst5Nw,217485
babel/locale-data/km_KH.dat,sha256=xVjkyVxn_hrWpEp6JOzSZKxZFDZ_3UQjRQsVPvBy0CM,608
babel/locale-data/kn.dat,sha256=enjouAVCKBfDX1k_-_1rS9HxV0sYKPZFYyRKLTPvWDk,294235
babel/locale-data/kn_IN.dat,sha256=Kzg5Bayf-ACbA0Nun8rTGYcbi5r2PmghFxlbyQIiKV8,631
babel/locale-data/ko.dat,sha256=KP44DmEQDxCWph4mCISPyEi4b8yu25zo4av6EZeFfu8,186908
babel/locale-data/ko_KP.dat,sha256=2Z1Rbojo6MHJGQdInFOjfZHbpRdwvZfM-FU_08oFGng,789
babel/locale-data/ko_KR.dat,sha256=y-3hO1aBM61NXG2L4o41zAPNlUvfA3RE14q_8SdarcM,608
babel/locale-data/kok.dat,sha256=bWPjrV3jPg3ZVUJeO2WHOurE7VAMJLjW_k6lNhTjAmA,212298
babel/locale-data/kok_IN.dat,sha256=e5cBMZY7kU_9H69kTorB93cUe7xFASM-2hUfGY3A-ec,632
babel/locale-data/ks.dat,sha256=ZnQcEMYXBJKxCnewD0sO5AKT7yoTPn5Uyo9cok8UA_M,114267
babel/locale-data/ks_Arab.dat,sha256=kfXVFhHX_NrcA7tZO6yYXym5wsDvpjma53urJPVeGJg,823
babel/locale-data/ks_Arab_IN.dat,sha256=_fjJMmIU0OJMR66po8yq9ByOzZZ3tomRqVt6RM4BJFw,631
babel/locale-data/ks_Deva.dat,sha256=s5caxRoYBdPp4TvaVDn0WUHF32sGoQOcAVm4dkWoIYU,14426
babel/locale-data/ks_Deva_IN.dat,sha256=_fjJMmIU0OJMR66po8yq9ByOzZZ3tomRqVt6RM4BJFw,631
babel/locale-data/ksb.dat,sha256=oU2e7m38AdRWc3gU0UgN_zJ0DWOnmnYLT1sf7FTLcnc,15906
babel/locale-data/ksb_TZ.dat,sha256=2Wzocj-_i0wMu7oi3-8ynqirioha6nG9PPI1-5EMbnY,590
babel/locale-data/ksf.dat,sha256=vKTJ0YEwumKMVfrGinmQpqcf1Fgy57_P704BoSKafnw,16394
babel/locale-data/ksf_CM.dat,sha256=1CFxJU8F4NverN5cPa9xvVI-we8x7wbZgP3UfXVnL0o,609
babel/locale-data/ksh.dat,sha256=JczgEekUovs196hUKmTVimYAi_-mD5e1c4R1behxV8k,90218
babel/locale-data/ksh_DE.dat,sha256=vTdZCAi8MAGFb4wE_zjnNTREloPZHNGc38eXQ0uwtPE,627
babel/locale-data/ku.dat,sha256=L6LL4EQd5Otsvlw1dylqdq-Bbd1LIBSRgHibOEEpMIU,28904
babel/locale-data/ku_TR.dat,sha256=EsO9U5XN30PqoR6A-7q72uLJ6An2BMuGbrh6sYrZoFU,608
babel/locale-data/kw.dat,sha256=mmKDRKFQFdtgt6oBk1djDlGjf128eWaM0JLoAfRnmUY,7284
babel/locale-data/kw_GB.dat,sha256=nvzq6ku288buMZIPacs8IGm5rrD0LdzYFZQxBe9a_jw,626
babel/locale-data/ky.dat,sha256=bYeO1jaE5fdyuW-q1o2Q8JB3q8n8dtkr51HPFj0V834,217317
babel/locale-data/ky_KG.dat,sha256=I9WGUgCDXB09jIycutdV0trTbhHFKvbM8Cr4_eTvHmk,608
babel/locale-data/lag.dat,sha256=nMQfiaN0hcrN8XNgim8YP0VfYeQ9QQOhvqW5BHS2mJQ,16822
babel/locale-data/lag_TZ.dat,sha256=gB3iS13Egu-2TLYBYwM2xbve9HxMHCQwgoxELuIuxTI,590
babel/locale-data/lb.dat,sha256=4mcQYwsG6SPRyeng90iXJCXA_uT7OklYRKkNdclsdo4,165664
babel/locale-data/lb_LU.dat,sha256=oksbNG3kkuxhnrv6goNlYcBj0Oejpr9-ptrmWHF6EW4,626
babel/locale-data/lg.dat,sha256=yPzj4yI0P-Mt5YWtejBoBVZISZkVV317778TVQFNqFg,16297
babel/locale-data/lg_UG.dat,sha256=1HeWA7IllosO0gp2T_nevwD0f2CSAx9lMfQYK-JpafA,612
babel/locale-data/lkt.dat,sha256=K0o21INPb8Q_d0GIbeGGeDG5JKL7L-EIUeOBGjt5di0,12459
babel/locale-data/lkt_US.dat,sha256=KoED03rqibBCmXUUHPR12gR0xc9ox489Wxavkf3hJl4,627
babel/locale-data/ln.dat,sha256=pyzay6sDbwkzEHsjhbVxFf4Fzqzsxs-_U15HuENuYZ0,25770
babel/locale-data/ln_AO.dat,sha256=Df8fip-BEQDkkdNenJMZYVEwNEFpJU3e7TBDFk1GCFw,609
babel/locale-data/ln_CD.dat,sha256=cya8q___2YF--XiQKag0Z2j67S_3MXvGMkqjjvao8Js,589
babel/locale-data/ln_CF.dat,sha256=GI1_WE8tFKny1XT5c7Vdr1xpgTYtA20qoi-LbfXcNmA,589
babel/locale-data/ln_CG.dat,sha256=gR1qJakj6apKRWJfeXchgBbbmOYiZJs-sWBiOVC4giI,589
babel/locale-data/lo.dat,sha256=wGwWp5gAsB8fylTWlz6LBpc3nNt-9VwqKQbYv6N-0Ek,229220
babel/locale-data/lo_LA.dat,sha256=Le3oiQxOdMmSpTmRje_U-gYUmJIgsRuIrll3v9Gvn9U,608
babel/locale-data/lrc.dat,sha256=pICbG0n1_MMZ4cMpGiiBIL2WhUvUvJCS9cCY6HSilgM,19127
babel/locale-data/lrc_IQ.dat,sha256=IulRzfQLGQNFx-m2GA1E-996l3AmXam6Kb2yxEU7Pzs,1228
babel/locale-data/lrc_IR.dat,sha256=Xwe6srYtOSobQ5_3dgtaFUJPpdCzPfqdMdFw5u3h7iE,652
babel/locale-data/lt.dat,sha256=LwdtB8KOA8cnONgQkXMSPxG4kFUW5uCOpxgsANb2khc,308452
babel/locale-data/lt_LT.dat,sha256=xpcc0-LW9jbhEMcG4_YJ_1Zh8gjMuO_pFWRRl71WVUI,626
babel/locale-data/lu.dat,sha256=Ww9oxo9l3kCNDotsLGhrJSky-b3FeaRJiyKY1onhtmk,15771
babel/locale-data/lu_CD.dat,sha256=NLQ9XNdydBzo-3BIWY7FrESS7yLG1BFyU8wsX_QclOw,589
babel/locale-data/luo.dat,sha256=tMfTl7UVUQOb_jTSSG32Pk7R0_ri8auQaFnLgsRRLiw,15748
babel/locale-data/luo_KE.dat,sha256=NEKNpjQX9ul04z2QZGvlKaYQEpG7qpLnz0fraetUD2w,609
babel/locale-data/luy.dat,sha256=6yMB7fLOMJ-w-dxwfJlfxjeajltDQxKMt73bVfdT7vE,15722
babel/locale-data/luy_KE.dat,sha256=3uCT5nrrTWh8Qcd2-x0vAMbsqdBfLbVNllWdTBPXVk0,609
babel/locale-data/lv.dat,sha256=RL8KMGuOeokpJDelSu5D57didSUP44776W5HWrjNO3o,235281
babel/locale-data/lv_LV.dat,sha256=DVQGeBkn2bfyW4oBFSk-FG5YDgYoPrcy4P1i2msqbKw,608
babel/locale-data/mai.dat,sha256=y7Y1wPM-ReX-bjG0D3vsymWT3fcfTJmxiZk2gkt0IGg,99156
babel/locale-data/mai_IN.dat,sha256=lZ93VuH0KWuLZAwFYQOlGidLcq19FwAh5FcTkbmWHIQ,632
babel/locale-data/mas.dat,sha256=uzGw-_qDWq5P1sNke_tbLXrk8cPR-uggmvTBgaqA_JM,17178
babel/locale-data/mas_KE.dat,sha256=H37wvJs04-E8bNfKwZQhqeDajPo6SvpdVwuo3PyJ1AY,609
babel/locale-data/mas_TZ.dat,sha256=9JwDj_IR1VKGVgWxstev2mrAXxIodBYOH4UDM6Q3q1o,611
babel/locale-data/mdf.dat,sha256=FzzNAmNSSd8LQICO8gBw9TkinQ9HdiHYHX4YBVJr-d4,2109
babel/locale-data/mdf_RU.dat,sha256=w_twves7EDDzHMYRpkpz-tGITmoVdJKAKEEKCFm8BWU,627
babel/locale-data/mer.dat,sha256=kvpoAf_LZotQs9PAucYDlQmniz8ExvHi7qrxFYW2IM8,15969
babel/locale-data/mer_KE.dat,sha256=99Q8eh6kJb1wkSHx_J0OroOC7WZ23Gp5IGAFc-NBQpc,609
babel/locale-data/mfe.dat,sha256=HAQX4356FaKY5d5ADqf6fI_u3qUCZfpXvDf4lj9F7rY,14788
babel/locale-data/mfe_MU.dat,sha256=TFnNwSIFyDkJUAVbw4Y2RyGH5uG4nvbKg8uNubPWXpA,590
babel/locale-data/mg.dat,sha256=tZ9Nn8GRFCKgG3hZW2zZCVB6WztCiorOqlr2s56s-74,23668
babel/locale-data/mg_MG.dat,sha256=cwl6h3aaMkDtvF9Ei8qvlnO4N1FTSI_VOEVa54g3eHs,589
babel/locale-data/mgh.dat,sha256=8CZhbKywmOf7-lBmOr4zwg-hFsooKAy4noBgSNcR3q8,10164
babel/locale-data/mgh_MZ.dat,sha256=uJyr7jkKxWqYOJ7CmhjAs8AKMOz_cWlojWjFXRj_jPc,609
babel/locale-data/mgo.dat,sha256=uqnN6sNCGvBF8XYAZWrrBopvGSHlqNzZVbKhSJL1bTU,8124
babel/locale-data/mgo_CM.dat,sha256=T5kZuEQ7hzI616QF05Grrv-RZb59B86medbIafdhrtU,609
babel/locale-data/mi.dat,sha256=mb2q5M6MYEw9JdrgG2yLkj1MGOJu7I3SghjGS4tBXso,49402
babel/locale-data/mi_NZ.dat,sha256=7o2jTlC9sR5dX2mxLI4qjVIr897Xd5keBTxs7a-_DYU,608
babel/locale-data/mk.dat,sha256=gotYl5HfwVuPga9lQxRgcUGFhfV8GCMnogxESzsEBWc,245719
babel/locale-data/mk_MK.dat,sha256=DtPgHruh_KrDRllM_vDipwCsbMWzk2bua0lfFsstTus,608
babel/locale-data/ml.dat,sha256=mSDbdz97X4a7fI4534Ad8ggthOjiclLfGUQkvUVvsqk,300165
babel/locale-data/ml_IN.dat,sha256=_vPZnTZA2VgZoDi31tfu-tR4uRzfj-cFFVMmcB8XZgI,631
babel/locale-data/mn.dat,sha256=8xz-lzvsgjwqsFv_PunI8IYlJIXy33vt7PWhWbyT_MA,225057
babel/locale-data/mn_MN.dat,sha256=gne5zuFemBThyeemcmnNvI751-rsRwCrCBUQ6uvuK4c,608
babel/locale-data/mni.dat,sha256=U00kkoFwKUuH4T8ucIeZHZXe0Ue4c3SB2dH93KVrk9k,15641
babel/locale-data/mni_Beng.dat,sha256=NiCHewI8Yl4k7ylwMAZVB7mtk6TZboLcvZl22n9uG9M,666
babel/locale-data/mni_Beng_IN.dat,sha256=Lx0qjRdIKxv05uZIp8e9W-Onti_kqLE-bZiu4yEgCOU,632
babel/locale-data/mr.dat,sha256=hapynpGulDrvY_UdSidkxScRy4QNZTvWJGHp_8SG-sU,267257
babel/locale-data/mr_IN.dat,sha256=RkYd5HIWUeP8yK3zFCRWvxvu3FzaK0ta7H1HTQQMUdY,631
babel/locale-data/ms.dat,sha256=rns-5OxYTKsqjNkKElD4ubOqN-Wb7OnRRlm2KWCnNqw,165372
babel/locale-data/ms_BN.dat,sha256=-wJL0kyLDl_lu6yByQqJ0beS7MI0Y7yhbdqhf9dKqco,1293
babel/locale-data/ms_ID.dat,sha256=xoDGTQo25tuchsYJ9tuKUR8snnWdEZahntfexmFUzS0,3386
babel/locale-data/ms_MY.dat,sha256=8RsVjifl5WL8sXV_aNTdgjqquxny2SsSBXc4KqJuqlY,608
babel/locale-data/ms_SG.dat,sha256=_nfWkz663QdJKVxb2AQQQUt_Hhl9bMk7hIQcqpVSPbU,627
babel/locale-data/mt.dat,sha256=7GGKU1xhHoemuBR1BdoYEswH7RQ5EXF-YkamOLLNkg8,81451
babel/locale-data/mt_MT.dat,sha256=2vQihLOtB1H_Ca6e9ZvGCgZ73gVlB_RBsBMFOw22cDs,608
babel/locale-data/mua.dat,sha256=48UIp_NblfFH5OridfSGbPsu3kjrW8RfHru_D7oq_NU,16468
babel/locale-data/mua_CM.dat,sha256=fQm0rv5p23ity5H_pu8jhbHVdaWDpqITuEPRev9q44I,609
babel/locale-data/my.dat,sha256=CLhDxoto2_5gH5POMwEq2Ezu_VtQASzstl9AUag1adM,224188
babel/locale-data/my_MM.dat,sha256=9DsxnFuIB4ImQJmOXpJ0Ujt1zMSUin-KV_a7R-irE-w,608
babel/locale-data/mzn.dat,sha256=TsRXekYELMXyVN0P2M42GaL2pW4Xa1PgHPjuGVfVsbE,65494
babel/locale-data/mzn_IR.dat,sha256=nw-iEKlN_b_C0VzjCY1SCElyqMgg3jQDZ4whD-lJrpg,652
babel/locale-data/naq.dat,sha256=wCWKpZK0g1HZifWQAlM0WCApFt-E6ZxkZ2CbcDMcem0,16486
babel/locale-data/naq_NA.dat,sha256=1Mh98XoWsJgytl-IvQuMXYJlLkYQvvoQ5_rptyu5ZME,590
babel/locale-data/nb.dat,sha256=EqRhBsxyFRYU5_pmSZt8rhKyC_zR1NdgMRrdJ9VziiI,1303
babel/locale-data/nb_NO.dat,sha256=bXb8K_1FTSDsqIXeZu2C0oYPCrTUpX0Y5GxKs3vXwBc,626
babel/locale-data/nb_SJ.dat,sha256=kCfUzsB6JilDQnWsVF1CFyg-7Ewq5VOdM-EWC7PJKP4,607
babel/locale-data/nd.dat,sha256=ujvmV_JGVJonS0uJcntaZ5bFQ7T63VSDs6OuiwNTeYc,16193
babel/locale-data/nd_ZW.dat,sha256=szM5GcRhUeN0V1SGix3RkcgDkRNJF7D3BWJMYMOkNlY,608
babel/locale-data/nds.dat,sha256=H3arSklBtJAFM88zWsj8kAbVOsopA8u0SNSs88sLMRs,50659
babel/locale-data/nds_DE.dat,sha256=wQlAFyMOkjMYQd9LVFTqLFt5GuntavA1RWhBf6E3DpM,627
babel/locale-data/nds_NL.dat,sha256=VPodVrFivmTiPf4v5OZ3Foc0_FaQwgRBuK7QiD8xmhU,627
babel/locale-data/ne.dat,sha256=jUvazn7_86VL7qNMpFhpsBkj_-CBW2ePB-1BNmKVLQE,268081
babel/locale-data/ne_IN.dat,sha256=Pc3G-flVbWniVZRu4RzMVYB099rVPhUvxUC1TiTCr8U,1265
babel/locale-data/ne_NP.dat,sha256=lhhB2jPqSBwBrxK6piIkUD0YHwGUNYdlmqlPBOJhb0o,608
babel/locale-data/nl.dat,sha256=7WAfJcvzFNSIvydSdFWiaukJaDT-ofCIb4n6Ajolsvs,230422
babel/locale-data/nl_AW.dat,sha256=6gmsswLqSrJ0XRfJJguCU0QFSU_dTpUOlPanbq5KGpM,611
babel/locale-data/nl_BE.dat,sha256=WOYalXajiwejntdaAmeO_f1ZWSGgetJ4LDoTroFc-JM,1883
babel/locale-data/nl_BQ.dat,sha256=E39EYJYegrYGpAdLuSfkizgwgoBtfyRp-1Crb_I5PkI,608
babel/locale-data/nl_CW.dat,sha256=Ho1si5eWdnrkT1_OA7ZWxarnzgfNdUmTlJLUkynzNck,611
babel/locale-data/nl_NL.dat,sha256=kLT_7mliQl_5XhGi5lU_guTBSD6V-DUK92xhdWQxzjk,626
babel/locale-data/nl_SR.dat,sha256=VVLYKCz48vdDn000ZzlokZnD1Qr1T7Tmn47j2wPG9fQ,669
babel/locale-data/nl_SX.dat,sha256=FTjEPrmwtpu8IQVixzrdl0dEyAH524Ml8cWUxd0pvjE,611
babel/locale-data/nmg.dat,sha256=hOOYbpl5DrBWlrBKa8RECAThwHgKpt16idICmteyn6A,16094
babel/locale-data/nmg_CM.dat,sha256=4wv7ftQl9xu_DkfdjxoJ97gcm-pMhM51OCXYX3CQ6gU,609
babel/locale-data/nn.dat,sha256=BXKL8qT-f_2zfYYrk89irMcPedQfTpZlct7CYu-hMuk,68937
babel/locale-data/nn_NO.dat,sha256=yc4l2fwSD9fD1-sCQirXzrAkfxIqD_garBegapCzWs8,626
babel/locale-data/nnh.dat,sha256=srVXo-_3IGaLJE0Nq102ATRloM7f0phx8KtdHQgrEoI,6619
babel/locale-data/nnh_CM.dat,sha256=azweVaEFbSCMHLptoZQ46yKcr_antYfr2pRmxIuZQCk,609
babel/locale-data/no.dat,sha256=dueGH7YWqe6BAKI1ETi6yK0URjSnALgSPwdf1i_KeVQ,228900
babel/locale-data/nus.dat,sha256=0FtsK466xY4GHZyIZKRffaGKa0Ul2Y_O_ngHuSl9_MQ,9094
babel/locale-data/nus_SS.dat,sha256=XQQtE8pKShDclBfN4yU1Rh_zEqrYFVndB-t2ScdGGUs,590
babel/locale-data/nyn.dat,sha256=mhYes12EtEEPrKejY-RSxGj7wxNmYo6M2CjN9J9UpFA,16138
babel/locale-data/nyn_UG.dat,sha256=i2Qcu0KO73WK35o2BvnFV9yd6dLK_p69_LtbVTMkCJA,613
babel/locale-data/oc.dat,sha256=nN4PqUndLnoZyLeZA7P4pQ1uEM6pTeYxVBk9dOpkyA4,48138
babel/locale-data/oc_ES.dat,sha256=pyZo4oiuTBN7SRNcw2W8mWgcujs55aopbj5Z7exvS04,50353
babel/locale-data/oc_FR.dat,sha256=1jMBWR278mIITTibDCr6aMMvIokKV5tb7h2G2HSEEOM,626
babel/locale-data/om.dat,sha256=v4Sz7bs1YwMS3UOjN-eHbFtq0coC8SlfYQFD8j1Gbm8,16714
babel/locale-data/om_ET.dat,sha256=MhyQf6WK9JWcW9TuiTrQwo2C8tKIELtGKBiJ5Scrt1A,608
babel/locale-data/om_KE.dat,sha256=A-EqNdXkq-j_TZK182yI6rnZYaFGGgAMyM76Q68FdG0,1566
babel/locale-data/or.dat,sha256=75X2u-YLKXzJarjFZ0qgGtbFNUklGD_Po0rxjtF_3CM,260770
babel/locale-data/or_IN.dat,sha256=tUmTnuoY49gDDU8WbdUCLyhv_2Yo-JJc_iTZlOJrH2Q,631
babel/locale-data/os.dat,sha256=8alaKdKfdtqHn2JZKivOhCWTk_X2vadz4xNo7dxAY9g,17369
babel/locale-data/os_GE.dat,sha256=bGm3R8Bz7k8wmb2GK_Ol83ud254rlJMbs26c1zN0w4Y,608
babel/locale-data/os_RU.dat,sha256=A2armkX5bdC0hKe6ie0WxB1IB0exTMHAZWk_0PNjFD4,668
babel/locale-data/pa.dat,sha256=w2w0dzS0bYMGeuvOLyjlPKUaXFR8rxLVOq8ZmxKN1Yk,265173
babel/locale-data/pa_Arab.dat,sha256=pMo66e7EXh4jqX9idnjtof0U6BGLUUAspwuJRf38QHE,3658
babel/locale-data/pa_Arab_PK.dat,sha256=-x9ycmOmzJ0ZIzy8J1ryO7nhRuBceY7ravgHBLEgyDY,608
babel/locale-data/pa_Guru.dat,sha256=risWFebHubet9zREjGQ-AIrrtBdOtKXo0yafgX6FhJU,1249
babel/locale-data/pa_Guru_IN.dat,sha256=tyUJVyrhCWckcBP10pfvLg2Xgv9shPpvWBaSiXg-G9c,631
babel/locale-data/pcm.dat,sha256=p3JBj9jZhW5xM-M7o_7zhWTr2YrrzcPwsCcfzWs0VLo,196060
babel/locale-data/pcm_NG.dat,sha256=E8wPtqkOJFSjTkU6T9V4RCZcer0Vc52PBvZ_LioI3S4,590
babel/locale-data/pis.dat,sha256=g1otCnQS7c1fVbp7tOM0fHgNsRKl0eqRGl_ACuVOubQ,2026
babel/locale-data/pis_SB.dat,sha256=Q-CrGezNS7j1SeE3H-fmeOjSlm9Q1jme5_UgbSgdpXw,590
babel/locale-data/pl.dat,sha256=m0NWwvtbURKFDBQirk7FMkd1ubkCnBfPzhry5y9EQ2Q,264632
babel/locale-data/pl_PL.dat,sha256=V62k9TTJ4FpN6KYLXzlsBBAMjHXnlNFuBnGoY9TBdDc,626
babel/locale-data/ps.dat,sha256=5-asLocA5cOg6CQLpGCOBR6z5y1aeVE42C2tGCc600w,191913
babel/locale-data/ps_AF.dat,sha256=goJChlJTUKnh7pZiMUkZiRMMth5lshKHVDZFwKq3Iwg,651
babel/locale-data/ps_PK.dat,sha256=_MSs-UxrpD1DJvl72MouRRhRmYbE8F6-MQ6q7ansCVw,7954
babel/locale-data/pt.dat,sha256=FcZCe3yg7WGBE8rIoeMSxpC-bLR6nZY-UEVYVEZQInM,213639
babel/locale-data/pt_AO.dat,sha256=cTQSDeLXeH4NvRK6Kydc1LB3QyQO9qOSwh4UE7Ngga0,995
babel/locale-data/pt_BR.dat,sha256=PoV5yebMbOhPwgtPQJ4qoKxOhQd3E5NCYcjjgOsvqu4,608
babel/locale-data/pt_CH.dat,sha256=aFs_w4Xa1ZxFfw0GnV7IAj92XFa0xpK9mN4uY4ynDho,626
babel/locale-data/pt_CV.dat,sha256=Yw4QSAys1d30PIGGjYLi1K-o0ME4nRnZ5xlO6mkj5KM,1012
babel/locale-data/pt_GQ.dat,sha256=mQbJaJxvrVnC7MaTHD8r36VIe7vTfJfudKJc5XjzFg0,589
babel/locale-data/pt_GW.dat,sha256=DTJrtZaU3wXwYHJvKkJK8BAZCcT9fSnsspJ25xuM4Po,975
babel/locale-data/pt_LU.dat,sha256=rgoGwpHgeahu8nLnT-uyVsrkD4CrWWwTCqDct0NBJmw,645
babel/locale-data/pt_MO.dat,sha256=b-vya6QGwLOo2Az-_AVHOv_iLSdOIn_MfvtHjiILt70,1608
babel/locale-data/pt_MZ.dat,sha256=hmhU3Y7HgDXrsyTUootEEdjCO4dy8wxGRvZRezeWq_Y,1015
babel/locale-data/pt_PT.dat,sha256=WwZHbYJ7c-nfmCVLNAJmY0trX9oQyWPyw1M_YCs7oi8,108281
babel/locale-data/pt_ST.dat,sha256=YBm07Nws76viG-9eMRgf3fn-n2B0jCptD5N5s6OWySA,995
babel/locale-data/pt_TL.dat,sha256=qG2kU_auBSaMJNnYn6fYwxspLJ3OK0EpL6Qd9-Qtzi4,975
babel/locale-data/qu.dat,sha256=iG04WcukZ__-tuEyDor87TRCifzP-ItVnlJYePHB6C0,127149
babel/locale-data/qu_BO.dat,sha256=CGWYNs1_AuQG3T-fYwe-q2AwDl9LAEITGRRYzc_MdKQ,836
babel/locale-data/qu_EC.dat,sha256=WewzwnSQA5llc9gb5UYy2ue5Y8_HRb1HnddOVIXcf6Q,810
babel/locale-data/qu_PE.dat,sha256=gT0fXlP3-rFSzIy6SdYVt-6viGPP79ukYHbBynqU4Bk,608
babel/locale-data/raj.dat,sha256=jmfvWd8qXmu6zLNN0o8sMPVMRKQK4Sc54gkVsIxMJn0,2382
babel/locale-data/raj_IN.dat,sha256=rtNdXBh0TKHj_SZqa0LasqbApMnH6JjoB0ErxAHdl_Q,632
babel/locale-data/rm.dat,sha256=vBqh6BlUgV1-SyrnyS4xDi8idwrxVkeyPRp_l519Zw0,102081
babel/locale-data/rm_CH.dat,sha256=atueKnCga8bqm2GrXOwBjQf1ypER1IAjcv4RX6Oz0Sk,626
babel/locale-data/rn.dat,sha256=-bI9OgKokbf8IgMM3oP2hRIDwxiQNrCjNckeKc5rwrg,16690
babel/locale-data/rn_BI.dat,sha256=II-eZWKAf73Hh0aGZifK2NLJvvXWws8a7Uv_2TUZ2VA,589
babel/locale-data/ro.dat,sha256=4ddZMNjhfXwrumpgsdnfQDRJ0_QNxk6JrR9nMe_dLK0,253761
babel/locale-data/ro_MD.dat,sha256=tkVS0RiHpOA2ZjCZbufnznw8aVIFj-XLoWr8whLVN3w,3215
babel/locale-data/ro_RO.dat,sha256=rFeMpPnG0zRek72AxhPuZAuJFKAuA-UL5fAyLAnPiQ8,608
babel/locale-data/rof.dat,sha256=cY0cJSbdQN9xc_I77-R-yS3zAKb3vdaFAOb3tBbGHQY,16033
babel/locale-data/rof_TZ.dat,sha256=6mZ6eFqNAqwuWCZuT7oZClLSv9eWSdGH0efVoQqxj40,590
babel/locale-data/root.dat,sha256=FPoQWneKRZ5iSw4qkvYZHgJXxBJpI_iobXugNUs_YL4,47196
babel/locale-data/ru.dat,sha256=snr4s5L6H60jN0z6LnMLowijgHzh2PvVXvMo_2HdF94,331028
babel/locale-data/ru_BY.dat,sha256=Pb4BHcT6RF6ONtgLhPcGQXQHVGj9dPrrodoI4ihsTSk,649
babel/locale-data/ru_KG.dat,sha256=iQapNW3xr7lH-HEbM7CIbdQwmUjm2Tgq3iJAMFUC7zc,632
babel/locale-data/ru_KZ.dat,sha256=OnFw_fadGFUzN0KL3WKvL0ekAwCCv5NOIhz2IFbHK0g,629
babel/locale-data/ru_MD.dat,sha256=vZr7Dz0UZlMeWWSisvdMuyOcLyreeihFbILXdQemOXM,627
babel/locale-data/ru_RU.dat,sha256=QhIIdAW2iPQ6LcErVIuxwvaBi1ku8V5-zsy1MZV1YU8,626
babel/locale-data/ru_UA.dat,sha256=-TaTfE4XD2sLCYI-KHYk8lImA1jZgy2VB4TN_2JLTvc,1668
babel/locale-data/rw.dat,sha256=LjIGfcohV-gKzJbqdq1kzd3ZzkDZ-AUkVGhvKdO2YF0,16318
babel/locale-data/rw_RW.dat,sha256=G6ta2DtZdiILzTdyZlXTCzoL-oRoF1gekRFCmN_dEyg,589
babel/locale-data/rwk.dat,sha256=viYAkJWmlaVDf5zroL8OfVBMHJ9NszvKaTOUcOusAs4,15920
babel/locale-data/rwk_TZ.dat,sha256=RtQRCyT2DbqRtc4uzP8Nna10O8KouCqtbtSxCJ-PukI,590
babel/locale-data/sa.dat,sha256=jVVSQ4-y03N8T-egnYSNVMV6wQWGBR0OpLibsnXLyns,24275
babel/locale-data/sa_IN.dat,sha256=TnFi858nrNslv9BVw1YOhOdXLaEcLVerU0d80vDNEn8,631
babel/locale-data/sah.dat,sha256=9vURJ5TYTA6F2ca1sWtSIeXpYzDphYR-lLOfEAZ9fJs,51323
babel/locale-data/sah_RU.dat,sha256=-Hi7VNsxTYaC-4G8qYQsnSPVMc5jXBYQJBvd5UeC-lo,627
babel/locale-data/saq.dat,sha256=_pUkBYP9ABjJxlLziRqoOQrS4UBTH0wKdHD3zQCr8RQ,16342
babel/locale-data/saq_KE.dat,sha256=uHKDZR4LUK5CGvcVC-dIpdYM3uY1KXVh6vkAOnOrc-w,609
babel/locale-data/sat.dat,sha256=NYlIpPrtO0FGh9rZZS5wHpSHgpzgTGwLHTVTnv2m-uI,69215
babel/locale-data/sat_Olck.dat,sha256=XNqbalNvgWolPY1M9vZXPpLzFkzYzjSAvKtoP1x5oBs,878
babel/locale-data/sat_Olck_IN.dat,sha256=Rx6KNBVSK2m0PvmKzotwxqBIp30-b5dCQU5-hqSB8tQ,632
babel/locale-data/sbp.dat,sha256=xWxrHPxrOIBWyI15vDu_pHlU98dhBfuc8-R9-xI1sHU,16388
babel/locale-data/sbp_TZ.dat,sha256=myr2BmLmSpSCCyRFCjm70nQfdeUAopZ29zxfemg6F8c,590
babel/locale-data/sc.dat,sha256=rnJtT9uk29gLAnlBAYJj_LVBd4suXscyPnMRbeParsA,199105
babel/locale-data/sc_IT.dat,sha256=mt4qFD-KvQnJaIjwufXWJyYxULQshy8_5w--RgEjDoQ,626
babel/locale-data/sd.dat,sha256=nMoOQ5gBv2lvBdQsRm1c0xUMUU4oK0YMEXz1dbFzO_Q,205523
babel/locale-data/sd_Arab.dat,sha256=EOWPc5-ACgE6NQEHILMBA_BP6mK35sTdUEEuEFCv748,852
babel/locale-data/sd_Arab_PK.dat,sha256=pNtPPmwu0jQK9V31EOv-lVoFiYwf1iHDxJmB5NNIZzU,608
babel/locale-data/sd_Deva.dat,sha256=pSY9wcb5Knj8WOy-KxMcMXGoWGtHY-_ne-TU5frjZaM,16521
babel/locale-data/sd_Deva_IN.dat,sha256=Uei2PSaYXixwn6VPwb7xeFMXt8I_jyM_myr-8lADGVs,631
babel/locale-data/se.dat,sha256=dZB1vNg7NmUYu4LgqN73hSRSbkU5RxO8t9cRtD8wHPU,73980
babel/locale-data/se_FI.dat,sha256=Do3w1bzT8_fqiynWUnKVuXRJazh43HYovQfsBBzXmwE,47217
babel/locale-data/se_NO.dat,sha256=k-BEm9_tnVXbt-H7pAtUU78dZfuiq7-cTcbsgsqISlg,626
babel/locale-data/se_SE.dat,sha256=BxFV9gNTLfUF3ibsRvgeuRnuDo99396qMA-89tpdEFY,667
babel/locale-data/seh.dat,sha256=rwsKF56ysgtQx4Nh18X_Xs8OyPu4WzcD3Dk-xk3Z1Lc,15769
babel/locale-data/seh_MZ.dat,sha256=feukobIWsGC_o5s_qb0UgFI7gzVCrNSydoRaXs0NUZ0,609
babel/locale-data/ses.dat,sha256=CwURrNdxyArjP2_vNSlc9GidQthPetAhzzp8viQzSCY,15857
babel/locale-data/ses_ML.dat,sha256=O7stcUKOw8ZkGmgnPqSWBCxPFA3_aDIcHZGAT9yRrtw,590
babel/locale-data/sg.dat,sha256=yZncKIajWQGDpHNjRKlZBFyCqCkLS9OWGi4H72PDYYw,16494
babel/locale-data/sg_CF.dat,sha256=dDZMdfhJBfy2ShSVhAopU2nIEEBnTssu3Vji2v9SpHg,589
babel/locale-data/shi.dat,sha256=yA8m8bjRvPNuY2DI2na8p_XrIn38ZJEAkiMNIFZK5_0,21895
babel/locale-data/shi_Latn.dat,sha256=nNOoXMih6DirYEMGxsNB1xqhsP0TK51lhGcRX1WaVC8,15477
babel/locale-data/shi_Latn_MA.dat,sha256=blTyj-JXuFz7wgjLjUC19rH4Emj7_-TOtMvBKb7qAus,590
babel/locale-data/shi_Tfng.dat,sha256=PmToPVEqibydgF2nxMw21pujbbqf4odWn7GlEqQL2u0,947
babel/locale-data/shi_Tfng_MA.dat,sha256=blTyj-JXuFz7wgjLjUC19rH4Emj7_-TOtMvBKb7qAus,590
babel/locale-data/si.dat,sha256=R0wPi_nY7qKI7fG625LTSAcwYmzvYLVuc2voQ7AYJxM,266857
babel/locale-data/si_LK.dat,sha256=2k1GulXssuQkuKMmj4J74iAYHlfh507gp6l75lKDJwg,608
babel/locale-data/sk.dat,sha256=DhwgNg_FnUSH1qORXgOCAMWVl2_XfYTLrcMr7uj6GTc,280987
babel/locale-data/sk_SK.dat,sha256=b8ugTdqk71Ge03FdSEhnOmH0wP5XeDSI40ys2hGovNQ,626
babel/locale-data/sl.dat,sha256=Ss2MfA63OAgjuD4OKVPttrlWGSNiIB7wDhHJzxynufI,269820
babel/locale-data/sl_SI.dat,sha256=V1oy5BlaUDjrX8b0jv9LK7Mgg4Yx84u-Iry4j3M8LYc,608
babel/locale-data/smn.dat,sha256=SSsMEq4OcWhrfDSBKRtWtRmGLD3ZseJiCgdU3geGepI,43444
babel/locale-data/smn_FI.dat,sha256=3FaHTO42uw4LsL2o9CnKHuk86tRNGaorVeYh7SPONWY,627
babel/locale-data/sms.dat,sha256=WzHRTGLfD_SLuD2c6xZ1bFjR3oibP-2mHaejlFtfnTg,6488
babel/locale-data/sms_FI.dat,sha256=a-XVjjPkU8UgWQiWiWEX3TnYJKSeIkNfT29ixLYSBns,627
babel/locale-data/sn.dat,sha256=3FYPTXW4rToBe58yh8lE4TyVaDteoQn2DqFT2HZbztQ,23364
babel/locale-data/sn_ZW.dat,sha256=R48ZM21PI5bjz154uuK-wccs9d-M9YMdiQLtX-rbG5k,608
babel/locale-data/so.dat,sha256=EqTBG60iBXZnoOrVNsSmCbHhLgLJZmElk-k2paumiY8,171086
babel/locale-data/so_DJ.dat,sha256=CWxbbQZ8iogPci77q4bpbWHOFBOKISwLOkqixb-TqRA,629
babel/locale-data/so_ET.dat,sha256=JKebALALzWT58gltRAjWVKl3LqFGiy1iD-nbFFsvfZ8,628
babel/locale-data/so_KE.dat,sha256=Ooas5zUI6mtrajAybdc2YQyFlS4RFNUxeXqT0pUQ2fo,1181
babel/locale-data/so_SO.dat,sha256=WtbiqTAukA-EouWNpajrPLIyRqUNmh0A6bcbXQywwqc,589
babel/locale-data/sq.dat,sha256=BVJXqN_e743eTE2clncOrrp-BHjUR25DqXHTuvP0dZI,207965
babel/locale-data/sq_AL.dat,sha256=061xsDws549-glqPY5No20svTFqs0pO6Cn9oUtwquVA,608
babel/locale-data/sq_MK.dat,sha256=8D6OAIV9T29UVST-ZD0zjtgYgrScEKaeZDaf8fJBk4E,1181
babel/locale-data/sq_XK.dat,sha256=nFWTBnEjpW6ux-oMbSov3ta96NrvwhjtQ80viYXFfKY,1160
babel/locale-data/sr.dat,sha256=JxSi4rurDPxygufZTRdapFsx4cj4YCYbJLSNKqU5bFw,300002
babel/locale-data/sr_Cyrl.dat,sha256=PqtXXFd7yu1Bweljv2UkBHFUYVPlIFY2abO3lfl8t4Y,1957
babel/locale-data/sr_Cyrl_BA.dat,sha256=O5nFwU7zgc7aRC1onhdASbCL76XaSViwnRod1ytH2Mo,44256
babel/locale-data/sr_Cyrl_ME.dat,sha256=tRDuVm4xa-0u19nMBjF6Neag0ivhimqO2qE6CrNeRaI,3881
babel/locale-data/sr_Cyrl_RS.dat,sha256=AAJ6aaa8D73J6na-RIjuqhEfLWKReHLwzYavdFaobhs,608
babel/locale-data/sr_Cyrl_XK.dat,sha256=hXdgzDWE5gDdWBbiNBaEHTl1hjEqqtd9dmnFXPFRkfc,2756
babel/locale-data/sr_Latn.dat,sha256=2yAeipJjthqVPqPRBW9SFy_z0cAPI9tcVvQ-FgA04rM,251406
babel/locale-data/sr_Latn_BA.dat,sha256=gbrYWDswB-XnTYN5WMzFLfxSUlU07Md0G91z7GxlSdE,34376
babel/locale-data/sr_Latn_ME.dat,sha256=Ouj7gX_BxAv_fcPlixWvXlNyA0s3ejIDM7T4QlTtJ4M,3250
babel/locale-data/sr_Latn_RS.dat,sha256=AAJ6aaa8D73J6na-RIjuqhEfLWKReHLwzYavdFaobhs,608
babel/locale-data/sr_Latn_XK.dat,sha256=bKshsVkR6h3Wsu8Tm7Ff8Um_evYxhPXWi-UOKfSk5JU,2362
babel/locale-data/su.dat,sha256=HAMD5fKf31wId1sY8pytCwfBSiWvm3KQn7EdbkuJDmk,13316
babel/locale-data/su_Latn.dat,sha256=AoqRqUqiJYE1G-ZRCIIhkYSRQ8s71qDefLwv70XrgZA,718
babel/locale-data/su_Latn_ID.dat,sha256=Hi1QalxGc49vElzHunyzz1Mfc6_1KgzXkGjcj04mq8c,608
babel/locale-data/sv.dat,sha256=RIv1363LTFVIj8Lpp1cKDkCbwcy8jOnzpDAOhVu7P4Q,237480
babel/locale-data/sv_AX.dat,sha256=4LqqSZFfMV2iRBS5TyTdWWKfdoN_ahxotRUbyuoaX8g,626
babel/locale-data/sv_FI.dat,sha256=i14KXwU5LSAWAly_iG6t5v_MvsMbYKRIRK5U1oZWVR0,2624
babel/locale-data/sv_SE.dat,sha256=OtNxgFxUFAH5mYJ4yGqp_wLMmnMu9mwVnvJ57BKUOKs,626
babel/locale-data/sw.dat,sha256=z_ffCKKDkW4if5coJAmi2PvVHjsxuFTVSDO-OnqYIJM,199985
babel/locale-data/sw_CD.dat,sha256=X5WmidVyJRqE-Zp2jpopvgLDygbcFVZ1QblhoeQGcaY,2535
babel/locale-data/sw_KE.dat,sha256=H6xUKk8kmKP4qtSTMk9drSIB2lBYIEcjjs0VCOJczAI,47284
babel/locale-data/sw_TZ.dat,sha256=rRGQVQ_Vp0bQ6_KnZTZDn7YDY5HDNiIsUMFLSnKD6nA,589
babel/locale-data/sw_UG.dat,sha256=GN6zqbWL7dor3RJWaJ7EwhMX8BIA6HVUzN7xWswPgbU,633
babel/locale-data/ta.dat,sha256=BbFku9hG2iOh3mZcMM3ejg4fAKkcPecyqMfUdZKnjMo,296033
babel/locale-data/ta_IN.dat,sha256=1D_ISTGx78nHVtYBoccQpH04o6CCL5dIIGRm4RWkMDg,631
babel/locale-data/ta_LK.dat,sha256=sHPH1bp1O7mbhnp0WgIyHfKckEIATHbtNtSGQPdbVSU,1181
babel/locale-data/ta_MY.dat,sha256=gBgYAEpdQXqeUzqDb2Xr4kkZoY7BX9E9hlA4tqPb6ts,1298
babel/locale-data/ta_SG.dat,sha256=yQUkhxL_2BLbNZK07ksyJkeHUyXXEk48BTA9xdtPqSI,1317
babel/locale-data/te.dat,sha256=-XRZj85I3oheGt_KxZKyVdnOyh-v1Zz2E7Q1pHVjHbI,283972
babel/locale-data/te_IN.dat,sha256=uRakP3CRkBJKNlCxMpMDOGOi5aeiq5OiLxBbUWn2NZk,631
babel/locale-data/teo.dat,sha256=9PB80gnhglGqbDXys03I3VyrTy3hJ_pDXjIr5hKy6FM,16558
babel/locale-data/teo_KE.dat,sha256=yZVnSmYqZ77jAPlyuyY_yivRqbj4dwbb99MW52EJNvU,630
babel/locale-data/teo_UG.dat,sha256=o5PkAO5zi67Lxbh5vKaOJF6qerkAFvJu3RrQ0iHlmwA,613
babel/locale-data/tg.dat,sha256=ZDMRczt33ZzkJqDJidDMuqYYXB2hUcNkA7OTI8IFGBU,50715
babel/locale-data/tg_TJ.dat,sha256=ge5GlIElwu5VzdLeWCCEz5A2-F9ihtOH9Ic9k5ii4wY,608
babel/locale-data/th.dat,sha256=6qW2D5IavP9zXADx6lvPugAS8CMcwgzmOu-Q3M72Uqc,255889
babel/locale-data/th_TH.dat,sha256=aQd6NJ_y5ObTF2koe4cI_s_mVdG0c7JfaiivpLN8M50,608
babel/locale-data/ti.dat,sha256=1oQ4l5eCSw1bk1TZ65kH-yKhVFA5HqvvPeRKKxNcqY8,105471
babel/locale-data/ti_ER.dat,sha256=UWHECZCp7POXzJ6tDxkFG0csM5fCwyaUzrds1udOM_g,935
babel/locale-data/ti_ET.dat,sha256=vT6Tl0BBaMupoRD4fb3kmM_Mufx2EGuqP460HO_Bh7Q,608
babel/locale-data/tk.dat,sha256=IdDrAPtgN9CejAGaRchktqV35ipWdeAbBn7MdD6rnR0,185418
babel/locale-data/tk_TM.dat,sha256=06szpphDghkTBac9nMge32AzZKeQdxXeZjsXF0X1-Nk,608
babel/locale-data/to.dat,sha256=JKtiRykykfcz0ZVMy29N-AlC4S4K6SDb1JRBMMvy4r4,180291
babel/locale-data/to_TO.dat,sha256=UaceT8b6KsoNoQd68finqhXDLVr_4GtcGFsgTwJaYTc,589
babel/locale-data/tok.dat,sha256=DMhhik6-uCFKycIKwVr1BmW8cz8cEH0RBWFZo6UQHVI,6024
babel/locale-data/tok_001.dat,sha256=bieoDt_x4vgLl3MQocuwqUytJRBvV3b2f50BRCQqVUk,666
babel/locale-data/tr.dat,sha256=jE686R_FheGeKO551cJn-xCXqohhPsfD1l0CxSo6-Ik,225193
babel/locale-data/tr_CY.dat,sha256=WncSUtrG90gWFsVn7YbRy_nJFKBDr25W3UA3UA7XoJo,1200
babel/locale-data/tr_TR.dat,sha256=lUyZY1ya9qqjmhdYhAkP6j4V953QWx_cC16GrVZCaYM,608
babel/locale-data/tt.dat,sha256=rj6jsvK5A1_XskXmcw1yom1j1FR4X5bDuDwfsdjFaZ4,42269
babel/locale-data/tt_RU.dat,sha256=MqxY1dPvSLsO7huGCYIhaTqwfGw9qHzq-oUt3VwVPyU,626
babel/locale-data/twq.dat,sha256=5bgKnEDdPL8hfCBagKLwLGdeL3bQtdPgC5CxilK_ibA,16082
babel/locale-data/twq_NE.dat,sha256=yv89EP--ZBgtvC_Vfy7UN37T7OktzntjGpRKfo89AW4,590
babel/locale-data/tzm.dat,sha256=-dG0db6bpfH2F-V7Zi46UeoJaRHWXhA1c5JAgky4OYA,16012
babel/locale-data/tzm_MA.dat,sha256=jOAK87vFm-WpZK130vSvCLE8fWxfjeyPs_G1elc5TMk,590
babel/locale-data/ug.dat,sha256=E1jh6inCH6MhPDSH-WjfdcUzgxsIRulS5uT2UbzuFHU,129453
babel/locale-data/ug_CN.dat,sha256=smJ1D2YZCHYeXD89a9bHHiAy6XUN217EPULgY1j0QDk,608
babel/locale-data/uk.dat,sha256=iaUP5Q2I1nawyxb8BLQ7eNuaYWkpmrbmhj6wjezD6nw,351099
babel/locale-data/uk_UA.dat,sha256=YE9ivxv_h3qwHTeFyWTV4gt5JaYgYdKQTLHHadAQQT8,608
babel/locale-data/ur.dat,sha256=AuBbKYxzSukAkRZqkSgfTEuixBl6cjcnTjNixn_BvJY,217844
babel/locale-data/ur_IN.dat,sha256=wQVX00wkPazO0nWhfYBGBtTOrK6w00S8XbP1pxUZlPE,12108
babel/locale-data/ur_PK.dat,sha256=VXzQfSYJAIlzcDjPva4UM67jhqIwDUqAVNRGB2YPcfI,608
babel/locale-data/uz.dat,sha256=lIxuZbqrBMCGPQOgE3ZO6_XhuZVrci6BptN_VpHU1Xw,191055
babel/locale-data/uz_Arab.dat,sha256=c87B8S9cvSqxKHcaBkceU4GEEWT_fpn8zx7cjOztsNY,3613
babel/locale-data/uz_Arab_AF.dat,sha256=ONnsHyim0Q-GRD6BAHPTj2Ri4aR41EB5HWhJQrKKXAU,651
babel/locale-data/uz_Cyrl.dat,sha256=7q25OHbYGwz5BbtMvZlj_qOAKZDaPuTj6_wn2UwaB5E,99893
babel/locale-data/uz_Cyrl_UZ.dat,sha256=D2g0Iy4gME1-ZrXDPgcs1VlFNW1FWKRD607VKgUsFwA,608
babel/locale-data/uz_Latn.dat,sha256=wkn_uCtrZQx7Ut7_pTVXVU9X956I30Nr4seILvPnZ_o,1265
babel/locale-data/uz_Latn_UZ.dat,sha256=D2g0Iy4gME1-ZrXDPgcs1VlFNW1FWKRD607VKgUsFwA,608
babel/locale-data/vai.dat,sha256=H7ljmMnBlgEI8nCu8gOdRYvFxNZlzQD-Fm1f0YB_Ad4,18875
babel/locale-data/vai_Latn.dat,sha256=RTRennEbxtunQQIy8cbDM2Hh60nuyDEUXnxEVLXjxC4,14892
babel/locale-data/vai_Latn_LR.dat,sha256=mFG8a5AB_Cnv2lwGAVg5SxhF0lgkrS4vB3UdqB1L8Y4,590
babel/locale-data/vai_Vaii.dat,sha256=rZi5j11eMQeE9MzTRK4Gl5EhqEy_X6o3V06k_E4ioOY,666
babel/locale-data/vai_Vaii_LR.dat,sha256=mFG8a5AB_Cnv2lwGAVg5SxhF0lgkrS4vB3UdqB1L8Y4,590
babel/locale-data/vi.dat,sha256=5mmgSfFGdPL4C1z2tlaFjjDlCGYB_irHxpLi3AdFsUQ,174755
babel/locale-data/vi_VN.dat,sha256=hn8-pr09TFtQwAvAau15ETGT4bmPay2o_LGOvLA6Bsk,608
babel/locale-data/vun.dat,sha256=AWyN2CNEE6DszZgTzM8M3ss5zyYkJW9CdoKQt3_eEUQ,15924
babel/locale-data/vun_TZ.dat,sha256=1lrpmdkRCqdDzX4Cel249MWWRGVDmubt9OiMf6Qsrnk,590
babel/locale-data/wae.dat,sha256=pmMkSCNe6am0CdgkjguMr-wlsNp9OFpOvihH-tDLZt8,30864
babel/locale-data/wae_CH.dat,sha256=5fOXgR-rrWoIYbf230jds8iOj1dsbvNW2Qv2XBNaCto,627
babel/locale-data/wo.dat,sha256=jSvLFYHtrygrAtzXNuzZEzjexJj2aV3uLGGvD89FWQ4,33105
babel/locale-data/wo_SN.dat,sha256=ryU-hZj708JELq9ldfmRU8I2EDihWGM_6v8QQY4qRuE,589
babel/locale-data/xh.dat,sha256=hTfakvIFKm2i2VKInt0rHpOwRODiH5Mbu_6EaftcywM,91043
babel/locale-data/xh_ZA.dat,sha256=LPaE6z0iRUaCSVd2CeuJzy_0GfhGCs2KgtYPHqLL18I,608
babel/locale-data/xog.dat,sha256=85N5V3duDQYQ2ADXFjRMN7hH2tbnYIQ1E8vQ8kmyfgQ,16414
babel/locale-data/xog_UG.dat,sha256=5B_ozUekB9sXcaT_-7brqH1nfv_XEP5CnB2PG84_JlM,613
babel/locale-data/yav.dat,sha256=I0TvJnZ19Fc25M87D-ATI9mAHjvDtx3VchzUvl5wT7U,15231
babel/locale-data/yav_CM.dat,sha256=y9SNKPJTMwmSdGc0MO-vn7hUeK4arphzRDp2zBFYigs,609
babel/locale-data/yi.dat,sha256=9TwnoSLuTD40FR5iZ6trDPcyh2ylrmFl-x75GZhLFxE,29985
babel/locale-data/yi_001.dat,sha256=wdIcCz3ZcZHFJqT28rBWo4iYmRffPPVWpxod_13KIYY,885
babel/locale-data/yo.dat,sha256=MfRZ7Iit3YLoQIspVzp05YuEdppMagPPOUf-fEvdy10,101614
babel/locale-data/yo_BJ.dat,sha256=Pa3FLKZE2h0nVFkAFrErWftfTJoQHZ3u1xiveH93yuA,42721
babel/locale-data/yo_NG.dat,sha256=vVCmItRDqtBEzSXYDsXGoiobciBukV84o_LpnAZRiDs,589
babel/locale-data/yrl.dat,sha256=y3M8uOEi80lM0p3yvQEnhpdNaeqX-TlBWM1IDggyGK8,207804
babel/locale-data/yrl_BR.dat,sha256=uG2fPhWqqf_l8cyyWlp_fw_sMFGCx-SZNaZsaoNAqqI,609
babel/locale-data/yrl_CO.dat,sha256=7stm4SEnQGrqlniqZqkpyShm_igDesuLf49E9JE8AmM,9298
babel/locale-data/yrl_VE.dat,sha256=hg4nTVty8CLQJTbPhlS-saewjGjvy6_ORMTFEBdjcV0,9298
babel/locale-data/yue.dat,sha256=g6wz78hxhsqVT9ZTUNttYQsCqbpd5KsglNgOx7_ZjbU,187955
babel/locale-data/yue_Hans.dat,sha256=Y38xjfIlWQPNE4GWXsS08MPOa9F_fk4-h9s0bs1oa_8,187729
babel/locale-data/yue_Hans_CN.dat,sha256=LJadpHvHHtY49YNddDLFCXFQh8RJwXFSMpSx-qskEuo,609
babel/locale-data/yue_Hant.dat,sha256=_BWk9N_79PzY7EPWu-O_M8j1ISYhkN29HEbuo-i0AoI,1279
babel/locale-data/yue_Hant_HK.dat,sha256=8iSo-1wkebNgS7h3iCFLd9s-nW8TuQ3-4UFUMUEmbMM,609
babel/locale-data/zgh.dat,sha256=xFCWLD7dumIJBqgzCU_1wRCOpSOiPmbTAFbvlFdYWk8,30464
babel/locale-data/zgh_MA.dat,sha256=sIGElmHSGowAduz_ykRA_-PotBTJaOqmBtRhXJ_swJc,590
babel/locale-data/zh.dat,sha256=0qz6YQZYzXqfcjSRCLIU2R8UUvSyEh2Vpfz8YUzADsU,193691
babel/locale-data/zh_Hans.dat,sha256=-JH1KTn0ibMkBj6gw2V2Q6ixLBL5x0n7B7AkCpU0TRI,1278
babel/locale-data/zh_Hans_CN.dat,sha256=Ccjjc2VePpDa-XQ5MBBDghVwwjZ1H5sswYMOPDkonJM,608
babel/locale-data/zh_Hans_HK.dat,sha256=5gkuu16wCLzaZLAZ6emlJl1fnOD_MewQ4shBTZXWg8A,3507
babel/locale-data/zh_Hans_MO.dat,sha256=SenQEOeTcvvqR1aHo8RZ4yurasD1HznXq5sTVh4MiQs,3639
babel/locale-data/zh_Hans_SG.dat,sha256=Wzt61cP2JJEU8PeMxjpmQ1u9ts_F-wcLRWWiDUYCf9s,3835
babel/locale-data/zh_Hant.dat,sha256=pLo0B1ymfwCFfu_PwpYrjkbuIidi7cmeplWLd290x4U,199641
babel/locale-data/zh_Hant_HK.dat,sha256=inVfOzruQGn1MRG0ygR55whUKoFEz3KeiG5TuiSvFWk,61576
babel/locale-data/zh_Hant_MO.dat,sha256=gTS5IdcTsRoMwAnANseIbj2nyflLj0tBQn2-4AFAaf4,630
babel/locale-data/zh_Hant_TW.dat,sha256=QYchBgi8JmeZgs7rQrUYn93CNNL9aavsOWYzAaTndwM,608
babel/locale-data/zu.dat,sha256=p_Lozk977_nOCFVDDVqSeZ_sVeZ05ok8YoSjSpL_r6o,183445
babel/locale-data/zu_ZA.dat,sha256=YO0tFWUiAdda0x3XEoL98oPNFGRLuk5OZ8DaR3lUX38,608
babel/localedata.py,sha256=vdTBpZsR2ExG9jBJLe42Xg-NKbm7XU7Pg5z0lIXod1Y,8239
babel/localtime/__init__.py,sha256=hHBBHcfWoTvnIOfahxHlxqNR7IL4A4yTuxxG7wDZWUk,1043
babel/localtime/__pycache__/__init__.cpython-38.pyc,,
babel/localtime/__pycache__/_fallback.cpython-38.pyc,,
babel/localtime/__pycache__/_helpers.cpython-38.pyc,,
babel/localtime/__pycache__/_unix.cpython-38.pyc,,
babel/localtime/__pycache__/_win32.cpython-38.pyc,,
babel/localtime/_fallback.py,sha256=0ak6R7ATmobpIlVjzQOK667bCMUjaFGcBWfL-IJlFEo,1207
babel/localtime/_helpers.py,sha256=cxCJUZ_rsEOyFEpaYiKUOcRDmcgM42o-5wEeeXO6t4w,1059
babel/localtime/_unix.py,sha256=7ExS68O5KpjqgZ6Dhho2WhxlYQYe2etJiW8BW2mXMCc,3455
babel/localtime/_win32.py,sha256=nSNnxSMOVAlvqvX50h9HSCzBfP7mj8njJ80JZ3pOIWk,3211
babel/messages/__init__.py,sha256=7UsGpKWLQkcEBwmt1oLAW-7xNOXaGXJIBI1upvXH5yU,349
babel/messages/__pycache__/__init__.cpython-38.pyc,,
babel/messages/__pycache__/catalog.cpython-38.pyc,,
babel/messages/__pycache__/checkers.cpython-38.pyc,,
babel/messages/__pycache__/extract.cpython-38.pyc,,
babel/messages/__pycache__/frontend.cpython-38.pyc,,
babel/messages/__pycache__/jslexer.cpython-38.pyc,,
babel/messages/__pycache__/mofile.cpython-38.pyc,,
babel/messages/__pycache__/plurals.cpython-38.pyc,,
babel/messages/__pycache__/pofile.cpython-38.pyc,,
babel/messages/catalog.py,sha256=f_aqwefMbFtlZHMDltAZvcrK8xoPAE0sJ6vy8pDVPT4,36301
babel/messages/checkers.py,sha256=o0hP1QFx_ZsjT9hnFRmeVjJ2GVnzDMQR_83X1UsRino,6373
babel/messages/extract.py,sha256=mZW20a8Qh89Ff_58LWEafkD7EgZU7vRtluj9-hgkIMs,34328
babel/messages/frontend.py,sha256=qugFqP7iJRb8gaXQVQpR2hSQOU2OFihfoMQjfkmeYSg,43713
babel/messages/jslexer.py,sha256=Neo9_DTIKwLDfubrRPfW73W0al_bup3TOnwwwPdckVg,7151
babel/messages/mofile.py,sha256=KJhrAi0c97vrZa25BV9-VAnCmKdp-w2_DNymkPf7OaY,7345
babel/messages/plurals.py,sha256=XZRVEIUv-qYyKd6SwbKfQms3hgdKTOiOVNeXPznjav8,7318
babel/messages/pofile.py,sha256=h-9rFVj3FnRcipfgabvskvSLujT6A552FF8mXWsmCtw,22323
babel/numbers.py,sha256=S-ppHTKE-DEgWu9JuYg7FRAcfBipxjt94PzPwx3IAP4,49550
babel/plural.py,sha256=zeLdLTojaHqsz0FKe0PLMqbOgWDpjav7vZmIdW3LQCs,23217
babel/py.typed,sha256=DtCsIDq6KOv2NOEdQjTbeMWJKRh6ZEL2E-6Mf1RLeMA,59
babel/support.py,sha256=geOJLaeT1o8I8gVad4ZbwCj5-9UhZGkTZoKLzlUNMII,26804
babel/units.py,sha256=nrUWAI_IdIXMM5JQDvXaf3K9ZS3ejZYFKIETV-4y-rM,12041
babel/util.py,sha256=1PIwDztbYvJC1e-KUVm5EiO8swmuaF-_wcae28b0QnI,7956

View file

@ -0,0 +1,5 @@
Wheel-Version: 1.0
Generator: bdist_wheel (0.41.2)
Root-Is-Purelib: true
Tag: py3-none-any

View file

@ -0,0 +1,20 @@
[babel.checkers]
num_plurals = babel.messages.checkers:num_plurals
python_format = babel.messages.checkers:python_format
[babel.extractors]
ignore = babel.messages.extract:extract_nothing
javascript = babel.messages.extract:extract_javascript
python = babel.messages.extract:extract_python
[console_scripts]
pybabel = babel.messages.frontend:main
[distutils.commands]
compile_catalog = babel.messages.frontend:compile_catalog
extract_messages = babel.messages.frontend:extract_messages
init_catalog = babel.messages.frontend:init_catalog
update_catalog = babel.messages.frontend:update_catalog
[distutils.setup_keywords]
message_extractors = babel.messages.frontend:check_message_extractors

View file

@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2017 Laurent LAPORTE
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.

View file

@ -0,0 +1,181 @@
Metadata-Version: 2.1
Name: Deprecated
Version: 1.2.14
Summary: Python @deprecated decorator to deprecate old python classes, functions or methods.
Home-page: https://github.com/tantale/deprecated
Author: Laurent LAPORTE
Author-email: tantale.solutions@gmail.com
License: MIT
Project-URL: Documentation, https://deprecated.readthedocs.io/en/latest/
Project-URL: Source, https://github.com/tantale/deprecated
Project-URL: Bug Tracker, https://github.com/tantale/deprecated/issues
Keywords: deprecate,deprecated,deprecation,warning,warn,decorator
Platform: any
Classifier: Development Status :: 5 - Production/Stable
Classifier: Environment :: Web Environment
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 2
Classifier: Programming Language :: Python :: 2.7
Classifier: Programming Language :: Python :: 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 :: 3.12
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*
Description-Content-Type: text/x-rst
License-File: LICENSE.rst
Requires-Dist: wrapt (<2,>=1.10)
Provides-Extra: dev
Requires-Dist: tox ; extra == 'dev'
Requires-Dist: PyTest ; extra == 'dev'
Requires-Dist: PyTest-Cov ; extra == 'dev'
Requires-Dist: bump2version (<1) ; extra == 'dev'
Requires-Dist: sphinx (<2) ; extra == 'dev'
Deprecated Library
------------------
Deprecated is Easy to Use
`````````````````````````
If you need to mark a function or a method as deprecated,
you can use the ``@deprecated`` decorator:
Save in a hello.py:
.. code:: python
from deprecated import deprecated
@deprecated(version='1.2.1', reason="You should use another function")
def some_old_function(x, y):
return x + y
class SomeClass(object):
@deprecated(version='1.3.0', reason="This method is deprecated")
def some_old_method(self, x, y):
return x + y
some_old_function(12, 34)
obj = SomeClass()
obj.some_old_method(5, 8)
And Easy to Setup
`````````````````
And run it:
.. code:: bash
$ pip install Deprecated
$ python hello.py
hello.py:15: DeprecationWarning: Call to deprecated function (or staticmethod) some_old_function.
(You should use another function) -- Deprecated since version 1.2.0.
some_old_function(12, 34)
hello.py:17: DeprecationWarning: Call to deprecated method some_old_method.
(This method is deprecated) -- Deprecated since version 1.3.0.
obj.some_old_method(5, 8)
You can document your code
``````````````````````````
Have you ever wonder how to document that some functions, classes, methods, etc. are deprecated?
This is now possible with the integrated Sphinx directives:
For instance, in hello_sphinx.py:
.. code:: python
from deprecated.sphinx import deprecated
from deprecated.sphinx import versionadded
from deprecated.sphinx import versionchanged
@versionadded(version='1.0', reason="This function is new")
def function_one():
'''This is the function one'''
@versionchanged(version='1.0', reason="This function is modified")
def function_two():
'''This is the function two'''
@deprecated(version='1.0', reason="This function will be removed soon")
def function_three():
'''This is the function three'''
function_one()
function_two()
function_three() # warns
help(function_one)
help(function_two)
help(function_three)
The result it immediate
```````````````````````
Run it:
.. code:: bash
$ python hello_sphinx.py
hello_sphinx.py:23: DeprecationWarning: Call to deprecated function (or staticmethod) function_three.
(This function will be removed soon) -- Deprecated since version 1.0.
function_three() # warns
Help on function function_one in module __main__:
function_one()
This is the function one
.. versionadded:: 1.0
This function is new
Help on function function_two in module __main__:
function_two()
This is the function two
.. versionchanged:: 1.0
This function is modified
Help on function function_three in module __main__:
function_three()
This is the function three
.. deprecated:: 1.0
This function will be removed soon
Links
`````
* `Python package index (PyPi) <https://pypi.python.org/pypi/deprecated>`_
* `GitHub website <https://github.com/tantale/deprecated>`_
* `Read The Docs <https://readthedocs.org/projects/deprecated>`_
* `EBook on Lulu.com <http://www.lulu.com/commerce/index.php?fBuyContent=21305117>`_
* `StackOverFlow Q&A <https://stackoverflow.com/a/40301488/1513933>`_
* `Development version
<https://github.com/tantale/deprecated/zipball/master#egg=Deprecated-dev>`_

View file

@ -0,0 +1,12 @@
Deprecated-1.2.14.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
Deprecated-1.2.14.dist-info/LICENSE.rst,sha256=HoPt0VvkGbXVveNy4yXlJ_9PmRX1SOfHUxS0H2aZ6Dw,1081
Deprecated-1.2.14.dist-info/METADATA,sha256=xQYvk5nwOfnkxxRD-VHkpE-sMu0IBHRZ8ayspypfkTs,5354
Deprecated-1.2.14.dist-info/RECORD,,
Deprecated-1.2.14.dist-info/WHEEL,sha256=a-zpFRIJzOq5QfuhBzbhiA1eHTzNCJn8OdRvhdNX0Rk,110
Deprecated-1.2.14.dist-info/top_level.txt,sha256=nHbOYawKPQQE5lQl-toUB1JBRJjUyn_m_Mb8RVJ0RjA,11
deprecated/__init__.py,sha256=ZphiULqDVrESSB0mLV2WA88JyhQxZSK44zuDGbV5k-g,349
deprecated/__pycache__/__init__.cpython-38.pyc,,
deprecated/__pycache__/classic.cpython-38.pyc,,
deprecated/__pycache__/sphinx.cpython-38.pyc,,
deprecated/classic.py,sha256=QugmUi7IhBvp2nDvMtyWqFDPRR43-9nfSZG1ZJSDpFM,9880
deprecated/sphinx.py,sha256=NqQ0oKGcVn6yUe23iGbCieCgvWbEDQSPt9QelbXJnDU,10258

View file

@ -0,0 +1,6 @@
Wheel-Version: 1.0
Generator: bdist_wheel (0.40.0)
Root-Is-Purelib: true
Tag: py2-none-any
Tag: py3-none-any

View file

@ -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.

View file

@ -0,0 +1,123 @@
Metadata-Version: 2.1
Name: Flask
Version: 2.2.5
Summary: A simple framework for building complex web applications.
Home-page: https://palletsprojects.com/p/flask
Author: Armin Ronacher
Author-email: armin.ronacher@active-4.com
Maintainer: Pallets
Maintainer-email: contact@palletsprojects.com
License: BSD-3-Clause
Project-URL: Donate, https://palletsprojects.com/donate
Project-URL: Documentation, https://flask.palletsprojects.com/
Project-URL: Changes, https://flask.palletsprojects.com/changes/
Project-URL: Source Code, https://github.com/pallets/flask/
Project-URL: Issue Tracker, https://github.com/pallets/flask/issues/
Project-URL: Twitter, https://twitter.com/PalletsTeam
Project-URL: Chat, https://discord.gg/pallets
Classifier: Development Status :: 5 - Production/Stable
Classifier: Environment :: Web Environment
Classifier: Framework :: Flask
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 :: Internet :: WWW/HTTP :: WSGI
Classifier: Topic :: Internet :: WWW/HTTP :: WSGI :: Application
Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
Requires-Python: >=3.7
Description-Content-Type: text/x-rst
License-File: LICENSE.rst
Requires-Dist: Werkzeug (>=2.2.2)
Requires-Dist: Jinja2 (>=3.0)
Requires-Dist: itsdangerous (>=2.0)
Requires-Dist: click (>=8.0)
Requires-Dist: importlib-metadata (>=3.6.0) ; python_version < "3.10"
Provides-Extra: async
Requires-Dist: asgiref (>=3.2) ; extra == 'async'
Provides-Extra: dotenv
Requires-Dist: python-dotenv ; extra == 'dotenv'
Flask
=====
Flask is a lightweight `WSGI`_ web application framework. It is designed
to make getting started quick and easy, with the ability to scale up to
complex applications. It began as a simple wrapper around `Werkzeug`_
and `Jinja`_ and has become one of the most popular Python web
application frameworks.
Flask offers suggestions, but doesn't enforce any dependencies or
project layout. It is up to the developer to choose the tools and
libraries they want to use. There are many extensions provided by the
community that make adding new functionality easy.
.. _WSGI: https://wsgi.readthedocs.io/
.. _Werkzeug: https://werkzeug.palletsprojects.com/
.. _Jinja: https://jinja.palletsprojects.com/
Installing
----------
Install and update using `pip`_:
.. code-block:: text
$ pip install -U Flask
.. _pip: https://pip.pypa.io/en/stable/getting-started/
A Simple Example
----------------
.. code-block:: python
# save this as app.py
from flask import Flask
app = Flask(__name__)
@app.route("/")
def hello():
return "Hello, World!"
.. code-block:: text
$ flask run
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
Contributing
------------
For guidance on setting up a development environment and how to make a
contribution to Flask, see the `contributing guidelines`_.
.. _contributing guidelines: https://github.com/pallets/flask/blob/main/CONTRIBUTING.rst
Donate
------
The Pallets organization develops and supports Flask and the libraries
it uses. 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://flask.palletsprojects.com/
- Changes: https://flask.palletsprojects.com/changes/
- PyPI Releases: https://pypi.org/project/Flask/
- Source Code: https://github.com/pallets/flask/
- Issue Tracker: https://github.com/pallets/flask/issues/
- Website: https://palletsprojects.com/p/flask/
- Twitter: https://twitter.com/PalletsTeam
- Chat: https://discord.gg/pallets

View file

@ -0,0 +1,53 @@
../../../bin/flask,sha256=XFk963gW5pC4Z_QB8pIcPwIWr-9_2sWSqVkjrpjJUXw,268
Flask-2.2.5.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
Flask-2.2.5.dist-info/LICENSE.rst,sha256=SJqOEQhQntmKN7uYPhHg9-HTHwvY-Zp5yESOf_N9B-o,1475
Flask-2.2.5.dist-info/METADATA,sha256=rZTjr5v4M7HB-zC-w2Y0ZU96OYSGBb-Hm15jlLJhs3g,3889
Flask-2.2.5.dist-info/RECORD,,
Flask-2.2.5.dist-info/WHEEL,sha256=pkctZYzUS4AYVn6dJ-7367OJZivF2e8RA9b_ZBjif18,92
Flask-2.2.5.dist-info/entry_points.txt,sha256=s3MqQpduU25y4dq3ftBYD6bMVdVnbMpZP-sUNw0zw0k,41
Flask-2.2.5.dist-info/top_level.txt,sha256=dvi65F6AeGWVU0TBpYiC04yM60-FX1gJFkK31IKQr5c,6
flask/__init__.py,sha256=GJgAILDWhW_DQljuoJ4pk9zBUy70zPPu-VZ6kLyiVI4,2890
flask/__main__.py,sha256=bYt9eEaoRQWdejEHFD8REx9jxVEdZptECFsV7F49Ink,30
flask/__pycache__/__init__.cpython-38.pyc,,
flask/__pycache__/__main__.cpython-38.pyc,,
flask/__pycache__/app.cpython-38.pyc,,
flask/__pycache__/blueprints.cpython-38.pyc,,
flask/__pycache__/cli.cpython-38.pyc,,
flask/__pycache__/config.cpython-38.pyc,,
flask/__pycache__/ctx.cpython-38.pyc,,
flask/__pycache__/debughelpers.cpython-38.pyc,,
flask/__pycache__/globals.cpython-38.pyc,,
flask/__pycache__/helpers.cpython-38.pyc,,
flask/__pycache__/logging.cpython-38.pyc,,
flask/__pycache__/scaffold.cpython-38.pyc,,
flask/__pycache__/sessions.cpython-38.pyc,,
flask/__pycache__/signals.cpython-38.pyc,,
flask/__pycache__/templating.cpython-38.pyc,,
flask/__pycache__/testing.cpython-38.pyc,,
flask/__pycache__/typing.cpython-38.pyc,,
flask/__pycache__/views.cpython-38.pyc,,
flask/__pycache__/wrappers.cpython-38.pyc,,
flask/app.py,sha256=ue4tEeDnr3m-eSEwz7OJ1_wafSYl3fl6eo-NLFgNNJQ,99141
flask/blueprints.py,sha256=fenhKP_Sh5eU6qtWeHacg1GVeun4pQzK2vq8sNDd1hY,27266
flask/cli.py,sha256=pLmnWObe_G4_ZAFQdh7kgwqPMxRXm4oUhaUSBpJMeq4,33532
flask/config.py,sha256=Ubo_juzSYsAKqD2vD3vm6mjsPo3EOJDdSEzYq8lKTJI,12585
flask/ctx.py,sha256=bGEQQuF2_cHqZ3ZNMeMeEG8HOLJkDlL88u2BBxCrRao,14829
flask/debughelpers.py,sha256=_RvAL3TW5lqMJeCVWtTU6rSDJC7jnRaBL6OEkVmooyU,5511
flask/globals.py,sha256=EX0XdX73BTWdVF0UHDSNet2ER3kI6sKveo3_o5IOs98,3187
flask/helpers.py,sha256=XTHRgLlyxeEzR988q63-4OY8RswTscR-5exFxK10CLU,25280
flask/json/__init__.py,sha256=TOwldHT3_kFaXHlORKi9yCWt7dbPNB0ovdHHQWlSRzY,11175
flask/json/__pycache__/__init__.cpython-38.pyc,,
flask/json/__pycache__/provider.cpython-38.pyc,,
flask/json/__pycache__/tag.cpython-38.pyc,,
flask/json/provider.py,sha256=jXCNypf11PN4ngQjEt6LnSdCWQ1yHIAkNLHlXQlCB-A,10674
flask/json/tag.py,sha256=fys3HBLssWHuMAIJuTcf2K0bCtosePBKXIWASZEEjnU,8857
flask/logging.py,sha256=WYng0bLTRS_CJrocGcCLJpibHf1lygHE_pg-KoUIQ4w,2293
flask/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
flask/scaffold.py,sha256=EKx-Tr5BXLzeKKvq3ZAi_2oUQVZuC4OJSJTocyDXsSo,35958
flask/sessions.py,sha256=adWCRnJYETJcjjhlcvUgZR5S0DMqKQctS0nzkY9g9Us,15927
flask/signals.py,sha256=H7QwDciK-dtBxinjKpexpglP0E6k0MJILiFWTItfmqU,2136
flask/templating.py,sha256=1P4OzvSnA2fsJTYgQT3G4owVKsuOz8XddCiR6jMHGJ0,7419
flask/testing.py,sha256=JtHRQY7mIH39SM4S51svAr8e7Xk87dqMb30Z6Dyv9TA,10706
flask/typing.py,sha256=KgxegTF9v9WvuongeF8LooIvpZPauzGrq9ZXf3gBlYc,2969
flask/views.py,sha256=LulttWL4owVFlgwrJi8GCNM4inC3xbs2IBlY31bdCS4,6765
flask/wrappers.py,sha256=el3tn1LgSUV0eNGgYMjKICT5I7qGJgbpIhvci4nrwQ8,5702

View file

@ -0,0 +1,5 @@
Wheel-Version: 1.0
Generator: bdist_wheel (0.40.0)
Root-Is-Purelib: true
Tag: py3-none-any

View file

@ -0,0 +1,2 @@
[console_scripts]
flask = flask.cli:main

View file

@ -0,0 +1,7 @@
Copyright (C) 2016 Cory Dolphin, Olin College
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.

View file

@ -0,0 +1,149 @@
Metadata-Version: 2.1
Name: Flask-Cors
Version: 3.0.10
Summary: A Flask extension adding a decorator for CORS support
Home-page: https://github.com/corydolphin/flask-cors
Author: Cory Dolphin
Author-email: corydolphin@gmail.com
License: MIT
Platform: any
Classifier: Environment :: Web Environment
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 2
Classifier: Programming Language :: Python :: 2.7
Classifier: Programming Language :: Python :: 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 :: Implementation :: CPython
Classifier: Programming Language :: Python :: Implementation :: PyPy
Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Dist: Flask (>=0.9)
Requires-Dist: Six
Flask-CORS
==========
|Build Status| |Latest Version| |Supported Python versions|
|License|
A Flask extension for handling Cross Origin Resource Sharing (CORS), making cross-origin AJAX possible.
This package has a simple philosophy: when you want to enable CORS, you wish to enable it for all use cases on a domain.
This means no mucking around with different allowed headers, methods, etc.
By default, submission of cookies across domains is disabled due to the security implications.
Please see the documentation for how to enable credential'ed requests, and please make sure you add some sort of `CSRF <http://en.wikipedia.org/wiki/Cross-site_request_forgery>`__ protection before doing so!
Installation
------------
Install the extension with using pip, or easy\_install.
.. code:: bash
$ pip install -U flask-cors
Usage
-----
This package exposes a Flask extension which by default enables CORS support on all routes, for all origins and methods.
It allows parameterization of all CORS headers on a per-resource level.
The package also contains a decorator, for those who prefer this approach.
Simple Usage
~~~~~~~~~~~~
In the simplest case, initialize the Flask-Cors extension with default arguments in order to allow CORS for all domains on all routes.
See the full list of options in the `documentation <https://flask-cors.corydolphin.com/en/latest/api.html#extension>`__.
.. code:: python
from flask import Flask
from flask_cors import CORS
app = Flask(__name__)
CORS(app)
@app.route("/")
def helloWorld():
return "Hello, cross-origin-world!"
Resource specific CORS
^^^^^^^^^^^^^^^^^^^^^^
Alternatively, you can specify CORS options on a resource and origin level of granularity by passing a dictionary as the `resources` option, mapping paths to a set of options.
See the full list of options in the `documentation <https://flask-cors.corydolphin.com/en/latest/api.html#extension>`__.
.. code:: python
app = Flask(__name__)
cors = CORS(app, resources={r"/api/*": {"origins": "*"}})
@app.route("/api/v1/users")
def list_users():
return "user example"
Route specific CORS via decorator
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
This extension also exposes a simple decorator to decorate flask routes with.
Simply add ``@cross_origin()`` below a call to Flask's ``@app.route(..)`` to allow CORS on a given route.
See the full list of options in the `decorator documentation <https://flask-cors.corydolphin.com/en/latest/api.html#decorator>`__.
.. code:: python
@app.route("/")
@cross_origin()
def helloWorld():
return "Hello, cross-origin-world!"
Documentation
-------------
For a full list of options, please see the full `documentation <https://flask-cors.corydolphin.com/en/latest/api.html>`__
Troubleshooting
---------------
If things aren't working as you expect, enable logging to help understand what is going on under the hood, and why.
.. code:: python
logging.getLogger('flask_cors').level = logging.DEBUG
Tests
-----
A simple set of tests is included in ``test/``.
To run, install nose, and simply invoke ``nosetests`` or ``python setup.py test`` to exercise the tests.
Contributing
------------
Questions, comments or improvements?
Please create an issue on `Github <https://github.com/corydolphin/flask-cors>`__, tweet at `@corydolphin <https://twitter.com/corydolphin>`__ or send me an email.
I do my best to include every contribution proposed in any way that I can.
Credits
-------
This Flask extension is based upon the `Decorator for the HTTP Access Control <http://flask.pocoo.org/snippets/56/>`__ written by Armin Ronacher.
.. |Build Status| image:: https://api.travis-ci.org/corydolphin/flask-cors.svg?branch=master
:target: https://travis-ci.org/corydolphin/flask-cors
.. |Latest Version| image:: https://img.shields.io/pypi/v/Flask-Cors.svg
:target: https://pypi.python.org/pypi/Flask-Cors/
.. |Supported Python versions| image:: https://img.shields.io/pypi/pyversions/Flask-Cors.svg
:target: https://img.shields.io/pypi/pyversions/Flask-Cors.svg
.. |License| image:: http://img.shields.io/:license-mit-blue.svg
:target: https://pypi.python.org/pypi/Flask-Cors/

View file

@ -0,0 +1,16 @@
Flask_Cors-3.0.10.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
Flask_Cors-3.0.10.dist-info/LICENSE,sha256=bhob3FSDTB4HQMvOXV9vLK4chG_Sp_SCsRZJWU-vvV0,1069
Flask_Cors-3.0.10.dist-info/METADATA,sha256=GGjB2MELGVMzpRA98u66-Y4kjXwJvRuEzuv9JuQaBpc,5382
Flask_Cors-3.0.10.dist-info/RECORD,,
Flask_Cors-3.0.10.dist-info/WHEEL,sha256=Z-nyYpwrcSqxfdux5Mbn_DQ525iP7J2DG3JgGvOYyTQ,110
Flask_Cors-3.0.10.dist-info/top_level.txt,sha256=aWye_0QNZPp_QtPF4ZluLHqnyVLT9CPJsfiGhwqkWuo,11
flask_cors/__init__.py,sha256=oJExwfR7yU3HAsmQ_EfL6KoLK3zq3J9HsET9r-56sfM,791
flask_cors/__pycache__/__init__.cpython-38.pyc,,
flask_cors/__pycache__/core.cpython-38.pyc,,
flask_cors/__pycache__/decorator.cpython-38.pyc,,
flask_cors/__pycache__/extension.cpython-38.pyc,,
flask_cors/__pycache__/version.cpython-38.pyc,,
flask_cors/core.py,sha256=N6dEVe5dffaQTw79Mc8IvEeTzvY_YsKCiOZ1lJ_PyNk,13894
flask_cors/decorator.py,sha256=iiwjUi0lVeCm4OJJHY5Cvuzj2nENbUns3Iq6zqKXuss,4937
flask_cors/extension.py,sha256=HTSAUEDH8mvTLLMVrcpfbtrdh5OXK72VUPk_FAoQhpU,7586
flask_cors/version.py,sha256=8OdYCyhDLC6EsmyL3_m3G4XCKOJMI20UlrLKmiyEoCE,23

View file

@ -0,0 +1,6 @@
Wheel-Version: 1.0
Generator: bdist_wheel (0.36.2)
Root-Is-Purelib: true
Tag: py2-none-any
Tag: py3-none-any

View file

@ -0,0 +1,20 @@
Copyright (c) 2022 Ali-Akber Saifee
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.

View file

@ -0,0 +1,193 @@
Metadata-Version: 2.1
Name: Flask-Limiter
Version: 2.9.2
Summary: Rate limiting for flask applications
Home-page: https://flask-limiter.readthedocs.org
Author: Ali-Akber Saifee
Author-email: ali@indydevs.org
License: MIT
Project-URL: Source, https://github.com/alisaifee/flask-limiter
Classifier: Development Status :: 5 - Production/Stable
Classifier: Environment :: Web Environment
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: MacOS
Classifier: Operating System :: POSIX :: Linux
Classifier: Operating System :: OS Independent
Classifier: Topic :: Software Development :: Libraries :: Python Modules
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
Requires-Python: >=3.7
License-File: LICENSE.txt
Requires-Dist: limits (>=2.8)
Requires-Dist: Flask (>=2)
Requires-Dist: ordered-set (<5,>4)
Requires-Dist: rich (<13,>=12)
Requires-Dist: typing-extensions (>=4)
Provides-Extra: memcached
Requires-Dist: limits[memcached] ; extra == 'memcached'
Provides-Extra: mongodb
Requires-Dist: limits[mongodb] ; extra == 'mongodb'
Provides-Extra: redis
Requires-Dist: limits[redis] ; extra == 'redis'
.. |ci| image:: https://github.com/alisaifee/flask-limiter/workflows/CI/badge.svg?branch=master
:target: https://github.com/alisaifee/flask-limiter/actions?query=branch%3Amaster+workflow%3ACI
.. |codecov| image:: https://codecov.io/gh/alisaifee/flask-limiter/branch/master/graph/badge.svg
:target: https://codecov.io/gh/alisaifee/flask-limiter
.. |pypi| image:: https://img.shields.io/pypi/v/Flask-Limiter.svg?style=flat-square
:target: https://pypi.python.org/pypi/Flask-Limiter
.. |license| image:: https://img.shields.io/pypi/l/Flask-Limiter.svg?style=flat-square
:target: https://pypi.python.org/pypi/Flask-Limiter
.. |docs| image:: https://readthedocs.org/projects/flask-limiter/badge/?version=latest
:target: https://flask-limiter.readthedocs.org/en/latest
*************
Flask-Limiter
*************
|docs| |ci| |codecov| |pypi| |license|
**Flask-Limiter** provides rate limiting features to `Flask <https://flask.palletsprojects.com>`_ applications.
----
Sponsored by `Zuplo <https://zuplo.link/3NuX0co>`_ a fully-managed API Gateway for developers.
Add `dynamic rate-limiting <https://zuplo.link/flask-dynamic-rate-limit>`_ authentication and more to any API in minutes.
Learn more at `zuplo.com <https://zuplo.link/3NuX0co>`_
----
You can configure rate limits at different levels such as:
- Application wide global limits per user
- Default limits per route
- By `Blueprints <https://flask-limiter.readthedocs.io/en/latest/recipes.html#rate-limiting-all-routes-in-a-blueprint>`_
- By `Class-based views <https://flask-limiter.readthedocs.io/en/latest/recipes.html#using-flask-pluggable-views>`_
- By `individual routes <https://flask-limiter.readthedocs.io/en/latest/index.html#decorators-to-declare-rate-limits>`_
**Flask-Limiter** can be `configured <https://flask-limiter.readthedocs.io/en/latest/configuration.html>`_ to fit your application in many ways, including:
- Persistance to various commonly used `storage backends <https://flask-limiter.readthedocs.io/en/latest/#configuring-a-storage-backend>`_
(such as Redis, Memcached & MongoDB)
via `limits <https://limits.readthedocs.io/en/stable/storage.html>`__
- Any rate limiting strategy supported by `limits <https://limits.readthedocs.io/en/stable/strategies.html>`__
Follow the quickstart below to get started or `read the documentation <http://flask-limiter.readthedocs.org/en/latest>`_ for more details.
Quickstart
===========
Install
-------
.. code-block:: bash
pip install Flask-Limiter
Add the rate limiter to your flask app
---------------------------------------
.. code-block:: python
# app.py
from flask import Flask
from flask_limiter import Limiter
from flask_limiter.util import get_remote_address
app = Flask(__name__)
limiter = Limiter(
app,
key_func=get_remote_address,
default_limits=["2 per minute", "1 per second"],
storage_uri="memory://",
# Redis
# storage_uri="redis://localhost:6379",
# Redis cluster
# storage_uri="redis+cluster://localhost:7000,localhost:7001,localhost:70002",
# Memcached
# storage_uri="memcached://localhost:11211",
# Memcached Cluster
# storage_uri="memcached://localhost:11211,localhost:11212,localhost:11213",
# MongoDB
# storage_uri="mongodb://localhost:27017",
strategy="fixed-window", # or "moving-window"
)
@app.route("/slow")
@limiter.limit("1 per day")
def slow():
return "24"
@app.route("/fast")
def fast():
return "42"
@app.route("/ping")
@limiter.exempt
def ping():
return 'PONG'
Inspect the limits using the command line interface
---------------------------------------------------
.. code-block:: bash
$ FLASK_APP=app:app flask limiter list
app
├── fast: /fast
│ ├── 2 per 1 minute
│ └── 1 per 1 second
├── ping: /ping
│ └── Exempt
└── slow: /slow
└── 1 per 1 day
Run the app
-----------
.. code-block:: bash
$ FLASK_APP=app:app flask run
Test it out
-----------
The ``fast`` endpoint respects the default rate limit while the
``slow`` endpoint uses the decorated one. ``ping`` has no rate limit associated
with it.
.. code-block:: bash
$ curl localhost:5000/fast
42
$ curl localhost:5000/fast
42
$ curl localhost:5000/fast
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<title>429 Too Many Requests</title>
<h1>Too Many Requests</h1>
<p>2 per 1 minute</p>
$ curl localhost:5000/slow
24
$ curl localhost:5000/slow
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<title>429 Too Many Requests</title>
<h1>Too Many Requests</h1>
<p>1 per 1 day</p>
$ curl localhost:5000/ping
PONG
$ curl localhost:5000/ping
PONG
$ curl localhost:5000/ping
PONG
$ curl localhost:5000/ping
PONG

View file

@ -0,0 +1,36 @@
Flask_Limiter-2.9.2.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
Flask_Limiter-2.9.2.dist-info/LICENSE.txt,sha256=92DDW6sU3SOesVpQcApB264W5u0Fo4LBgeU6FH5NO2E,1061
Flask_Limiter-2.9.2.dist-info/METADATA,sha256=ovPuraF5TorTWCnOMiPUmBCFAzj5gC4yjRHZ4t9A7no,6286
Flask_Limiter-2.9.2.dist-info/RECORD,,
Flask_Limiter-2.9.2.dist-info/WHEEL,sha256=2wepM1nk4DS4eFpYrW1TTqPcoGNfHhhO_i5m4cOimbo,92
Flask_Limiter-2.9.2.dist-info/entry_points.txt,sha256=XP1DLGAtSzSTO-1e0l2FR9chlucKvsGCgh_wfCO9oj8,54
Flask_Limiter-2.9.2.dist-info/top_level.txt,sha256=R6yEWxkN3qksR5mTrqbdyx6fadLmgetYxMw3pekXEwQ,14
flask_limiter/__init__.py,sha256=lcF4k4Kh9OAo9SlTinTcE6LBOjuVJfnn67vop3n5SHw,470
flask_limiter/__pycache__/__init__.cpython-38.pyc,,
flask_limiter/__pycache__/_compat.cpython-38.pyc,,
flask_limiter/__pycache__/_version.cpython-38.pyc,,
flask_limiter/__pycache__/commands.cpython-38.pyc,,
flask_limiter/__pycache__/constants.cpython-38.pyc,,
flask_limiter/__pycache__/errors.cpython-38.pyc,,
flask_limiter/__pycache__/extension.cpython-38.pyc,,
flask_limiter/__pycache__/manager.cpython-38.pyc,,
flask_limiter/__pycache__/typing.cpython-38.pyc,,
flask_limiter/__pycache__/util.cpython-38.pyc,,
flask_limiter/__pycache__/version.cpython-38.pyc,,
flask_limiter/__pycache__/wrappers.cpython-38.pyc,,
flask_limiter/_compat.py,sha256=jrUYRoIo4jOXp5JDWgpL77F6Cuj_0iX7ySsTOfYrPs8,379
flask_limiter/_version.py,sha256=jXei210YJN6r1PyxlzOfgmPWAR5eEAmyKgEhBbb70MI,497
flask_limiter/commands.py,sha256=1LC_WSvIoEhyFtor7ZI4kkO2bS69FokgaNecKwhdILw,21897
flask_limiter/constants.py,sha256=LEO1MEKn-qxoXO9Se6SE7_i7jwH8kozL9XvxqaYOwCE,2560
flask_limiter/contrib/__init__.py,sha256=Yr06Iy3i_F1cwTSGcGWOxMHOZaQnySiRFBfsH8Syric,28
flask_limiter/contrib/__pycache__/__init__.cpython-38.pyc,,
flask_limiter/contrib/__pycache__/util.cpython-38.pyc,,
flask_limiter/contrib/util.py,sha256=xYEHNkvH2m5-hZTmfklGnWJhGQ6axzsxXqIlEaXwFOI,270
flask_limiter/errors.py,sha256=EiBorsY_Ee1kHAwvG2qlL1Fcd8kt62QOmtqqftGmRUQ,1082
flask_limiter/extension.py,sha256=dmwFrwgEj7xDDC5-OBgw5884SOPPlPWylMaslsK_EPg,46822
flask_limiter/manager.py,sha256=NtJdS7nG3aide3R21wv5ZUiQM5tU3k244M_641EAOYQ,11818
flask_limiter/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
flask_limiter/typing.py,sha256=6AM1TvsZYsxOrNsXVuHpQzo9palzHyigTlNc7V7VQH4,387
flask_limiter/util.py,sha256=-Spircol_8JRgExHNOxrf1cX8VmPMEbKAXrPqkNS4ts,940
flask_limiter/version.py,sha256=YwkF3dtq1KGzvmL3iVGctA8NNtGlK_0arrzZkZGVjUs,47
flask_limiter/wrappers.py,sha256=kCO9yJ9BzxKSm-HLz5rpf63A8PZpOMUHdnWQvwJYG80,4908

View file

@ -0,0 +1,5 @@
Wheel-Version: 1.0
Generator: bdist_wheel (0.38.4)
Root-Is-Purelib: true
Tag: py3-none-any

View file

@ -0,0 +1,2 @@
[flask.commands]
limiter = flask_limiter.commands:cli

View file

@ -0,0 +1,31 @@
Copyright (c) 2010 by danjac.
Some rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* 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.
* The names of the contributors may not 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
OWNER 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.

View file

@ -0,0 +1,35 @@
Metadata-Version: 2.1
Name: Flask-Mail
Version: 0.9.1
Summary: Flask extension for sending email
Home-page: https://github.com/rduplain/flask-mail
Author: Dan Jacob
Author-email: danjac354@gmail.com
Maintainer: Ron DuPlain
Maintainer-email: ron.duplain@gmail.com
License: BSD
Platform: any
Classifier: Development Status :: 4 - Beta
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 :: Software Development :: Libraries :: Python Modules
License-File: LICENSE
Requires-Dist: Flask
Requires-Dist: blinker
Flask-Mail
----------
A Flask extension for sending email messages.
Please refer to the online documentation for details.
Links
`````
* `documentation <http://packages.python.org/Flask-Mail>`_

View file

@ -0,0 +1,8 @@
Flask_Mail-0.9.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
Flask_Mail-0.9.1.dist-info/LICENSE,sha256=4Rm-c4W3yEpsCANoWqvmytM2PUSFd7btDLd_SpVbEFQ,1449
Flask_Mail-0.9.1.dist-info/METADATA,sha256=4BYevWzO1kqmbef7VAVuyYpcDL1mXdc7O2L4OGLRfVA,960
Flask_Mail-0.9.1.dist-info/RECORD,,
Flask_Mail-0.9.1.dist-info/WHEEL,sha256=pkctZYzUS4AYVn6dJ-7367OJZivF2e8RA9b_ZBjif18,92
Flask_Mail-0.9.1.dist-info/top_level.txt,sha256=DXVYMmoZEmH0LMYIpymMBM-ekAlhlAu1TCcWn2GM9OE,11
__pycache__/flask_mail.cpython-38.pyc,,
flask_mail.py,sha256=IHsiylgTIXOu6i0MQQcVGqBArCl9pR2XzkBMxj1_lr8,17950

View file

@ -0,0 +1,5 @@
Wheel-Version: 1.0
Generator: bdist_wheel (0.40.0)
Root-Is-Purelib: true
Tag: py3-none-any

View file

@ -0,0 +1,20 @@
The MIT License (MIT)
Copyright (c) 2013 Miguel Grinberg
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.

View file

@ -0,0 +1,86 @@
Metadata-Version: 2.1
Name: Flask-Migrate
Version: 4.0.5
Summary: SQLAlchemy database migrations for Flask applications using Alembic.
Home-page: https://github.com/miguelgrinberg/flask-migrate
Author: Miguel Grinberg
Author-email: miguel.grinberg@gmail.com
License: MIT
Project-URL: Bug Tracker, https://github.com/miguelgrinberg/flask-migrate/issues
Classifier: Environment :: Web Environment
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Requires-Python: >=3.6
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: Flask >=0.9
Requires-Dist: Flask-SQLAlchemy >=1.0
Requires-Dist: alembic >=1.9.0
Flask-Migrate
=============
[![Build status](https://github.com/miguelgrinberg/flask-migrate/workflows/build/badge.svg)](https://github.com/miguelgrinberg/flask-migrate/actions)
Flask-Migrate is an extension that handles SQLAlchemy database migrations for Flask applications using Alembic. The database operations are provided as command-line arguments under the `flask db` command.
Installation
------------
Install Flask-Migrate with `pip`:
pip install Flask-Migrate
Example
-------
This is an example application that handles database migrations through Flask-Migrate:
```python
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///app.db'
db = SQLAlchemy(app)
migrate = Migrate(app, db)
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(128))
```
With the above application you can create the database or enable migrations if the database already exists with the following command:
$ flask db init
Note that the `FLASK_APP` environment variable must be set according to the Flask documentation for this command to work. This will add a `migrations` folder to your application. The contents of this folder need to be added to version control along with your other source files.
You can then generate an initial migration:
$ flask db migrate
The migration script needs to be reviewed and edited, as Alembic currently does not detect every change you make to your models. In particular, Alembic is currently unable to detect indexes. Once finalized, the migration script also needs to be added to version control.
Then you can apply the migration to the database:
$ flask db upgrade
Then each time the database models change repeat the `migrate` and `upgrade` commands.
To sync the database in another system just refresh the `migrations` folder from source control and run the `upgrade` command.
To see all the commands that are available run this command:
$ flask db --help
Resources
---------
- [Documentation](http://flask-migrate.readthedocs.io/en/latest/)
- [pypi](https://pypi.python.org/pypi/Flask-Migrate)
- [Change Log](https://github.com/miguelgrinberg/Flask-Migrate/blob/master/CHANGES.md)

View file

@ -0,0 +1,30 @@
Flask_Migrate-4.0.5.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
Flask_Migrate-4.0.5.dist-info/LICENSE,sha256=kfkXGlJQvKy3Y__6tAJ8ynIp1HQfeROXhL8jZU1d-DI,1082
Flask_Migrate-4.0.5.dist-info/METADATA,sha256=d-EcnhZa_vyVAph2u84OpGIteJaBmqLQxO5Rf6wUI7Y,3095
Flask_Migrate-4.0.5.dist-info/RECORD,,
Flask_Migrate-4.0.5.dist-info/WHEEL,sha256=yQN5g4mg4AybRjkgi-9yy4iQEFibGQmlz78Pik5Or-A,92
Flask_Migrate-4.0.5.dist-info/top_level.txt,sha256=jLoPgiMG6oR4ugNteXn3IHskVVIyIXVStZOVq-AWLdU,14
flask_migrate/__init__.py,sha256=-JFdExGtr7UrwCpmjYvTfzFHqMjE7AmP0Rr3T53tBNU,10037
flask_migrate/__pycache__/__init__.cpython-38.pyc,,
flask_migrate/__pycache__/cli.cpython-38.pyc,,
flask_migrate/cli.py,sha256=H-N4NNS5HyEB61HpUADLU8pW3naejyDPgeEbzEqG5-w,10298
flask_migrate/templates/aioflask-multidb/README,sha256=Ek4cJqTaxneVjtkue--BXMlfpfp3MmJRjqoZvnSizww,43
flask_migrate/templates/aioflask-multidb/__pycache__/env.cpython-38.pyc,,
flask_migrate/templates/aioflask-multidb/alembic.ini.mako,sha256=SjYEmJKzz6K8QfuZWtLJAJWcCKOdRbfUhsVlpgv8ock,857
flask_migrate/templates/aioflask-multidb/env.py,sha256=UcjeqkAbyUjTkuQFmCFPG7QOvqhco8-uGp8QEbto0T8,6573
flask_migrate/templates/aioflask-multidb/script.py.mako,sha256=198VPxVEN3NZ3vHcRuCxSoI4XnOYirGWt01qkbPKoJw,1246
flask_migrate/templates/aioflask/README,sha256=KKqWGl4YC2RqdOdq-y6quTDW0b7D_UZNHuM8glM1L-c,44
flask_migrate/templates/aioflask/__pycache__/env.cpython-38.pyc,,
flask_migrate/templates/aioflask/alembic.ini.mako,sha256=SjYEmJKzz6K8QfuZWtLJAJWcCKOdRbfUhsVlpgv8ock,857
flask_migrate/templates/aioflask/env.py,sha256=m6ZtBhdpwuq89vVeLTWmNT-1NfJZqarC_hsquCdR9bw,3478
flask_migrate/templates/aioflask/script.py.mako,sha256=8_xgA-gm_OhehnO7CiIijWgnm00ZlszEHtIHrAYFJl0,494
flask_migrate/templates/flask-multidb/README,sha256=AfiP5foaV2odZxXxuUuSIS6YhkIpR7CsOo2mpuxwHdc,40
flask_migrate/templates/flask-multidb/__pycache__/env.cpython-38.pyc,,
flask_migrate/templates/flask-multidb/alembic.ini.mako,sha256=SjYEmJKzz6K8QfuZWtLJAJWcCKOdRbfUhsVlpgv8ock,857
flask_migrate/templates/flask-multidb/env.py,sha256=F44iqsAxLTVBN_zD8CMUkdE7Aub4niHMmo5wl9mY4Uw,6190
flask_migrate/templates/flask-multidb/script.py.mako,sha256=198VPxVEN3NZ3vHcRuCxSoI4XnOYirGWt01qkbPKoJw,1246
flask_migrate/templates/flask/README,sha256=JL0NrjOrscPcKgRmQh1R3hlv1_rohDot0TvpmdM27Jk,41
flask_migrate/templates/flask/__pycache__/env.cpython-38.pyc,,
flask_migrate/templates/flask/alembic.ini.mako,sha256=SjYEmJKzz6K8QfuZWtLJAJWcCKOdRbfUhsVlpgv8ock,857
flask_migrate/templates/flask/env.py,sha256=ibK1hsdOsOBzXNU2yQoAIza7f_EFzaVSWwON_NSpNzQ,3344
flask_migrate/templates/flask/script.py.mako,sha256=8_xgA-gm_OhehnO7CiIijWgnm00ZlszEHtIHrAYFJl0,494

View file

@ -0,0 +1,5 @@
Wheel-Version: 1.0
Generator: bdist_wheel (0.41.2)
Root-Is-Purelib: true
Tag: py3-none-any

View file

@ -0,0 +1,132 @@
Authors
=======
A huge thanks to all of our contributors:
- Adam Chainz
- Alec Nikolas Reiter
- Alex Gaynor
- Alex M
- Alex Morken
- Andrew Dunham
- Andriy Yurchuk
- Anil Kulkarni
- Antonio Dourado
- Antonio Herraiz
- Ares Ou
- Artur Rodrigues
- Axel Haustant
- Belousow Makc
- Benjamin Dopplinger
- Bennett, Bryan
- Bohan Zhang
- Bryan Bennett
- Bulat Bochkariov
- Cameron Brandon White
- Catherine Devlin
- Dan Quirk
- Daniele Esposti
- Dario Bertini
- David Arnold
- David Baumgold
- David Boucha
- David Crawford
- Dimitris Theodorou
- Doug Black
- Evan Dale Aromin
- Eyal Levin
- Francesco Della Vedova
- Frank Stratton
- Garret Raziel
- Gary Belvin
- Gilles Dartiguelongue
- Giorgio Salluzzo
- Guillaume BINET
- Heston Liebowitz
- Hu WQ
- Jacob Magnusson
- James Booth
- James Ogura
- James Turk
- Jeff Widman
- Joakim Ekberg
- Johannes
- Jordan Yelloz
- Josh Friend
- Joshua C. Randall
- Joshua Randall
- José Fernández Ramos
- Juan Rossi
- JuneHyeon Bae
- Kamil Gałuszka
- Kevin Burke
- Kevin Deldycke
- Kevin Funk
- Kyle Conroy
- Lance Ingle
- Lars Holm Nielsen
- Luiz Armesto
- Malthe Borch
- Marek Hlobil
- Matt Wright
- Max Mautner
- Max Peterson
- Maxim
- Michael Hwang
- Michael Newman
- Miguel Grinberg
- Mihai Tomescu
- Neil Halelamien
- Nicolas Harraudeau
- Pavel Tyslyatsky
- Petrus J.v.Rensburg
- Philippe Ndiaye
- Piotr Husiatyński
- Prasanna Swaminathan
- Robert Warner
- Rod Cloutier
- Ryan Horn
- Rémi Alvergnat
- Sam Kimbrel
- Samarth Shah
- Sami Jaktholm
- Sander Sink
- Sasha Baranov
- Saul Diez-Guerra
- Sergey Romanov
- Shreyans Sheth
- Steven Leggett
- Sven-Hendrik Haase
- Usman Ehtesham Gul
- Victor Neo
- Vlad Frolov
- Vladimir Pal
- WooParadog
- Yaniv Aknin
- akash
- bret barker
- hachichaud
- jbouzekri
- jobou
- johnrichter
- justanr
- k-funk
- kelvinhammond
- kenjones
- kieran gorman
- kumy
- lyschoening
- mailto1587
- mniebla
- mozillazg
- muchosalsa
- nachinius
- nixdata
- papaeye
- pingz
- saml
- siavashg
- silasray
- soasme
- ueg1990
- y-p

View file

@ -0,0 +1,25 @@
Copyright (c) 2013, Twilio, Inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
- 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.
- Neither the name of the Twilio, Inc. 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.

View file

@ -0,0 +1,29 @@
Metadata-Version: 2.1
Name: Flask-RESTful
Version: 0.3.10
Summary: Simple framework for creating REST APIs
Home-page: https://www.github.com/flask-restful/flask-restful/
Author: Twilio API Team
Author-email: help@twilio.com
License: BSD
Project-URL: Source, https://github.com/flask-restful/flask-restful
Platform: any
Classifier: Framework :: Flask
Classifier: Programming Language :: Python :: 2
Classifier: Programming Language :: Python :: 2.7
Classifier: Programming Language :: Python :: 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: License :: OSI Approved :: BSD License
License-File: LICENSE
License-File: AUTHORS.md
Requires-Dist: aniso8601 (>=0.82)
Requires-Dist: Flask (>=0.8)
Requires-Dist: six (>=1.3.0)
Requires-Dist: pytz
Provides-Extra: docs
Requires-Dist: sphinx ; extra == 'docs'

View file

@ -0,0 +1,27 @@
Flask_RESTful-0.3.10.dist-info/AUTHORS.md,sha256=HBq00z_VgMI2xfwfUobrU16_qamdouMkpNxbR0BzaVg,1992
Flask_RESTful-0.3.10.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
Flask_RESTful-0.3.10.dist-info/LICENSE,sha256=PFjoO0Jk5okmshAgMix5-RZTC0sFT_EJWpC_CtQcCyM,1485
Flask_RESTful-0.3.10.dist-info/METADATA,sha256=eTeg3NLzPPlJxKSMhedGPPQvRaQm-9lMafpxwIddLT8,1018
Flask_RESTful-0.3.10.dist-info/RECORD,,
Flask_RESTful-0.3.10.dist-info/WHEEL,sha256=a-zpFRIJzOq5QfuhBzbhiA1eHTzNCJn8OdRvhdNX0Rk,110
Flask_RESTful-0.3.10.dist-info/top_level.txt,sha256=lNpWPlejgBAtMhCUwz_FTyJH12ul1mBZ-Uv3ZK1HiGg,14
flask_restful/__init__.py,sha256=KDyCbekXcfGMyV6E7neY6ZJ8b8GdM6eLtJbtRmn_nL8,28624
flask_restful/__pycache__/__init__.cpython-38.pyc,,
flask_restful/__pycache__/__version__.cpython-38.pyc,,
flask_restful/__pycache__/fields.cpython-38.pyc,,
flask_restful/__pycache__/inputs.cpython-38.pyc,,
flask_restful/__pycache__/reqparse.cpython-38.pyc,,
flask_restful/__version__.py,sha256=JbZfv76t9J7HHmoA2wdjKemYHpQE0jhBfMJIil6HEsg,46
flask_restful/fields.py,sha256=43GbFejZ3kiOb20A1QuzLXjevfsxMZSbmpOpGtW56vo,13018
flask_restful/inputs.py,sha256=561w8fjLqBq4I_7yXPHJM567ijWhpuf8d8uZnKzTehA,9118
flask_restful/representations/__init__.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
flask_restful/representations/__pycache__/__init__.cpython-38.pyc,,
flask_restful/representations/__pycache__/json.cpython-38.pyc,,
flask_restful/representations/json.py,sha256=swKwnbt7v2ioHfHkqhqbzIu_yrcP0ComlSl49IGFJOo,873
flask_restful/reqparse.py,sha256=-xZmkyrvDFfGvFFokTtXe4J-2PWnNX4EfKolhkT995E,14681
flask_restful/utils/__init__.py,sha256=jgedvOLGeTk4Sqox4WHE_vAFLP0T_PrLHO4PXaqFqxw,723
flask_restful/utils/__pycache__/__init__.cpython-38.pyc,,
flask_restful/utils/__pycache__/cors.cpython-38.pyc,,
flask_restful/utils/__pycache__/crypto.cpython-38.pyc,,
flask_restful/utils/cors.py,sha256=cZiqaHhIn0w66spRoSIdC-jIn4X_b6OlVms5eGF4Ess,2084
flask_restful/utils/crypto.py,sha256=q3PBvAYMJYybbqqQlKNF_Pqeyo9h3x5jFJuVqtEA5bA,996

View file

@ -0,0 +1,6 @@
Wheel-Version: 1.0
Generator: bdist_wheel (0.40.0)
Root-Is-Purelib: true
Tag: py2-none-any
Tag: py3-none-any

View file

@ -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.

View file

@ -0,0 +1,94 @@
Metadata-Version: 2.1
Name: Flask-SQLAlchemy
Version: 2.5.1
Summary: Adds SQLAlchemy support to your Flask application.
Home-page: https://github.com/pallets/flask-sqlalchemy
Author: Armin Ronacher
Author-email: armin.ronacher@active-4.com
Maintainer: Pallets
Maintainer-email: contact@palletsprojects.com
License: BSD-3-Clause
Project-URL: Documentation, https://flask-sqlalchemy.palletsprojects.com/
Project-URL: Code, https://github.com/pallets/flask-sqlalchemy
Project-URL: Issue tracker, https://github.com/pallets/flask-sqlalchemy/issues
Platform: UNKNOWN
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: Programming Language :: Python :: 2
Classifier: Programming Language :: Python :: 2.7
Classifier: Programming Language :: Python :: 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 :: Implementation :: CPython
Classifier: Programming Language :: Python :: Implementation :: PyPy
Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >= 2.7, != 3.0.*, != 3.1.*, != 3.2.*, != 3.3.*
Requires-Dist: Flask (>=0.10)
Requires-Dist: SQLAlchemy (>=0.8.0)
Flask-SQLAlchemy
================
Flask-SQLAlchemy is an extension for `Flask`_ that adds support for
`SQLAlchemy`_ to your application. It aims to simplify using SQLAlchemy
with Flask by providing useful defaults and extra helpers that make it
easier to accomplish common tasks.
Installing
----------
Install and update using `pip`_:
.. code-block:: text
$ pip install -U Flask-SQLAlchemy
A Simple Example
----------------
.. code-block:: python
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///example.sqlite"
db = SQLAlchemy(app)
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String, unique=True, nullable=False)
email = db.Column(db.String, unique=True, nullable=False)
db.session.add(User(name="Flask", email="example@example.com"))
db.session.commit()
users = User.query.all()
Links
-----
- Documentation: https://flask-sqlalchemy.palletsprojects.com/
- Releases: https://pypi.org/project/Flask-SQLAlchemy/
- Code: https://github.com/pallets/flask-sqlalchemy
- Issue tracker: https://github.com/pallets/flask-sqlalchemy/issues
- Test status: https://travis-ci.org/pallets/flask-sqlalchemy
- Test coverage: https://codecov.io/gh/pallets/flask-sqlalchemy
.. _Flask: https://palletsprojects.com/p/flask/
.. _SQLAlchemy: https://www.sqlalchemy.org
.. _pip: https://pip.pypa.io/en/stable/quickstart/

View file

@ -0,0 +1,14 @@
Flask_SQLAlchemy-2.5.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
Flask_SQLAlchemy-2.5.1.dist-info/LICENSE.rst,sha256=SJqOEQhQntmKN7uYPhHg9-HTHwvY-Zp5yESOf_N9B-o,1475
Flask_SQLAlchemy-2.5.1.dist-info/METADATA,sha256=vVCeMtTM_xOrUVoVyemeNaTUI5L9iXa16NsiMDDOgFU,3128
Flask_SQLAlchemy-2.5.1.dist-info/RECORD,,
Flask_SQLAlchemy-2.5.1.dist-info/WHEEL,sha256=Z-nyYpwrcSqxfdux5Mbn_DQ525iP7J2DG3JgGvOYyTQ,110
Flask_SQLAlchemy-2.5.1.dist-info/top_level.txt,sha256=w2K4fNNoTh4HItoFfz2FRQShSeLcvHYrzU_sZov21QU,17
flask_sqlalchemy/__init__.py,sha256=IaupgTRkQnY05KPLYvfiNnJdrmwoyfsxaiyGtrEYfO4,40738
flask_sqlalchemy/__pycache__/__init__.cpython-38.pyc,,
flask_sqlalchemy/__pycache__/_compat.cpython-38.pyc,,
flask_sqlalchemy/__pycache__/model.cpython-38.pyc,,
flask_sqlalchemy/__pycache__/utils.cpython-38.pyc,,
flask_sqlalchemy/_compat.py,sha256=yua0ZSgVWwi56QpEgwaPInzkNQ9PFb7YQdvEk3dImXo,821
flask_sqlalchemy/model.py,sha256=bd2mIv9LA1A2MZkQObgnMUCSrxNvyqplaSkCxyxKNxY,4988
flask_sqlalchemy/utils.py,sha256=4eHqAbYElnJ3NbSAHhuINckoAHDABoxjleMJD0iKgyg,1390

View file

@ -0,0 +1,6 @@
Wheel-Version: 1.0
Generator: bdist_wheel (0.36.2)
Root-Is-Purelib: true
Tag: py2-none-any
Tag: py3-none-any

View file

@ -0,0 +1 @@
flask_sqlalchemy

View file

@ -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.

View file

@ -0,0 +1,113 @@
Metadata-Version: 2.1
Name: Jinja2
Version: 3.1.2
Summary: A very fast and expressive template engine.
Home-page: https://palletsprojects.com/p/jinja/
Author: Armin Ronacher
Author-email: armin.ronacher@active-4.com
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: Twitter, https://twitter.com/PalletsTeam
Project-URL: Chat, https://discord.gg/pallets
Platform: UNKNOWN
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/
- Website: https://palletsprojects.com/p/jinja/
- Twitter: https://twitter.com/PalletsTeam
- Chat: https://discord.gg/pallets

View file

@ -0,0 +1,58 @@
Jinja2-3.1.2.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
Jinja2-3.1.2.dist-info/LICENSE.rst,sha256=O0nc7kEF6ze6wQ-vG-JgQI_oXSUrjp3y4JefweCUQ3s,1475
Jinja2-3.1.2.dist-info/METADATA,sha256=PZ6v2SIidMNixR7MRUX9f7ZWsPwtXanknqiZUmRbh4U,3539
Jinja2-3.1.2.dist-info/RECORD,,
Jinja2-3.1.2.dist-info/WHEEL,sha256=G16H4A3IeoQmnOrYV4ueZGKSjhipXx8zc8nu9FGlvMA,92
Jinja2-3.1.2.dist-info/entry_points.txt,sha256=zRd62fbqIyfUpsRtU7EVIFyiu1tPwfgO7EvPErnxgTE,59
Jinja2-3.1.2.dist-info/top_level.txt,sha256=PkeVWtLb3-CqjWi1fO29OCbj55EhX_chhKrCdrVe_zs,7
jinja2/__init__.py,sha256=8vGduD8ytwgD6GDSqpYc2m3aU-T7PKOAddvVXgGr_Fs,1927
jinja2/__pycache__/__init__.cpython-38.pyc,,
jinja2/__pycache__/_identifier.cpython-38.pyc,,
jinja2/__pycache__/async_utils.cpython-38.pyc,,
jinja2/__pycache__/bccache.cpython-38.pyc,,
jinja2/__pycache__/compiler.cpython-38.pyc,,
jinja2/__pycache__/constants.cpython-38.pyc,,
jinja2/__pycache__/debug.cpython-38.pyc,,
jinja2/__pycache__/defaults.cpython-38.pyc,,
jinja2/__pycache__/environment.cpython-38.pyc,,
jinja2/__pycache__/exceptions.cpython-38.pyc,,
jinja2/__pycache__/ext.cpython-38.pyc,,
jinja2/__pycache__/filters.cpython-38.pyc,,
jinja2/__pycache__/idtracking.cpython-38.pyc,,
jinja2/__pycache__/lexer.cpython-38.pyc,,
jinja2/__pycache__/loaders.cpython-38.pyc,,
jinja2/__pycache__/meta.cpython-38.pyc,,
jinja2/__pycache__/nativetypes.cpython-38.pyc,,
jinja2/__pycache__/nodes.cpython-38.pyc,,
jinja2/__pycache__/optimizer.cpython-38.pyc,,
jinja2/__pycache__/parser.cpython-38.pyc,,
jinja2/__pycache__/runtime.cpython-38.pyc,,
jinja2/__pycache__/sandbox.cpython-38.pyc,,
jinja2/__pycache__/tests.cpython-38.pyc,,
jinja2/__pycache__/utils.cpython-38.pyc,,
jinja2/__pycache__/visitor.cpython-38.pyc,,
jinja2/_identifier.py,sha256=_zYctNKzRqlk_murTNlzrju1FFJL7Va_Ijqqd7ii2lU,1958
jinja2/async_utils.py,sha256=dHlbTeaxFPtAOQEYOGYh_PHcDT0rsDaUJAFDl_0XtTg,2472
jinja2/bccache.py,sha256=mhz5xtLxCcHRAa56azOhphIAe19u1we0ojifNMClDio,14061
jinja2/compiler.py,sha256=Gs-N8ThJ7OWK4-reKoO8Wh1ZXz95MVphBKNVf75qBr8,72172
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=6uHIcc7ZblqOMdx_uYNKqRnnwAF0_nzbyeMP9FFtuh4,61349
jinja2/exceptions.py,sha256=ioHeHrWwCWNaXX1inHmHVblvc4haO7AXsjCp3GfWvx0,5071
jinja2/ext.py,sha256=ivr3P7LKbddiXDVez20EflcO3q2aHQwz9P_PgWGHVqE,31502
jinja2/filters.py,sha256=9js1V-h2RlyW90IhLiBGLM2U-k6SCy2F4BUUMgB3K9Q,53509
jinja2/idtracking.py,sha256=GfNmadir4oDALVxzn3DL9YInhJDr69ebXeA2ygfuCGA,10704
jinja2/lexer.py,sha256=DW2nX9zk-6MWp65YR2bqqj0xqCvLtD-u9NWT8AnFRxQ,29726
jinja2/loaders.py,sha256=BfptfvTVpClUd-leMkHczdyPNYFzp_n7PKOJ98iyHOg,23207
jinja2/meta.py,sha256=GNPEvifmSaU3CMxlbheBOZjeZ277HThOPUTf1RkppKQ,4396
jinja2/nativetypes.py,sha256=DXgORDPRmVWgy034H0xL8eF7qYoK3DrMxs-935d0Fzk,4226
jinja2/nodes.py,sha256=i34GPRAZexXMT6bwuf5SEyvdmS-bRCy9KMjwN5O6pjk,34550
jinja2/optimizer.py,sha256=tHkMwXxfZkbfA1KmLcqmBMSaz7RLIvvItrJcPoXTyD8,1650
jinja2/parser.py,sha256=nHd-DFHbiygvfaPtm9rcQXJChZG7DPsWfiEsqfwKerY,39595
jinja2/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
jinja2/runtime.py,sha256=5CmD5BjbEJxSiDNTFBeKCaq8qU4aYD2v6q2EluyExms,33476
jinja2/sandbox.py,sha256=Y0xZeXQnH6EX5VjaV2YixESxoepnRbW_3UeQosaBU3M,14584
jinja2/tests.py,sha256=Am5Z6Lmfr2XaH_npIfJJ8MdXtWsbLjMULZJulTAj30E,5905
jinja2/utils.py,sha256=u9jXESxGn8ATZNVolwmkjUVu4SA-tLgV0W7PcSfPfdQ,23965
jinja2/visitor.py,sha256=MH14C6yq24G_KVtWzjwaI7Wg14PCJIYlWW1kpkxYak0,3568

View file

@ -0,0 +1,5 @@
Wheel-Version: 1.0
Generator: bdist_wheel (0.37.1)
Root-Is-Purelib: true
Tag: py3-none-any

Some files were not shown because too many files have changed in this diff Show more