mirror of
https://github.com/xtream1101/humblebundle-downloader.git
synced 2024-11-20 08:49:17 +01:00
formatting change. replaced setuptools with poetry
This commit is contained in:
parent
e6fa9e93ee
commit
623a64d501
191
.markdownlint.yaml
Normal file
191
.markdownlint.yaml
Normal file
@ -0,0 +1,191 @@
|
||||
# Example markdownlint configuration with all properties set to their default value
|
||||
|
||||
# Default state for all rules
|
||||
default: true
|
||||
|
||||
# MD001/heading-increment : Heading levels should only increment by one level at a time : https://github.com/DavidAnson/markdownlint/blob/v0.33.0/doc/md001.md
|
||||
MD001: true
|
||||
|
||||
# MD007/ul-indent : Unordered list indentation : https://github.com/DavidAnson/markdownlint/blob/v0.33.0/doc/md007.md
|
||||
MD007:
|
||||
# Spaces for indent
|
||||
indent: 4
|
||||
# Whether to indent the first level of the list
|
||||
start_indented: false
|
||||
# Spaces for first level indent (when start_indented is set)
|
||||
start_indent: 4
|
||||
|
||||
# MD009/no-trailing-spaces : Trailing spaces : https://github.com/DavidAnson/markdownlint/blob/v0.33.0/doc/md009.md
|
||||
MD009:
|
||||
# Spaces for line break
|
||||
br_spaces: 2
|
||||
# Allow spaces for empty lines in list items
|
||||
list_item_empty_lines: false
|
||||
# Include unnecessary breaks
|
||||
strict: false
|
||||
|
||||
# MD010/no-hard-tabs : Hard tabs : https://github.com/DavidAnson/markdownlint/blob/v0.33.0/doc/md010.md
|
||||
MD010:
|
||||
# Include code blocks
|
||||
code_blocks: true
|
||||
# Fenced code languages to ignore
|
||||
ignore_code_languages: []
|
||||
# Number of spaces for each hard tab
|
||||
spaces_per_tab: 4
|
||||
|
||||
# MD012/no-multiple-blanks : Multiple consecutive blank lines : https://github.com/DavidAnson/markdownlint/blob/v0.33.0/doc/md012.md
|
||||
MD012:
|
||||
# Consecutive blank lines
|
||||
maximum: 2
|
||||
|
||||
# MD013/line-length : Line length : https://github.com/DavidAnson/markdownlint/blob/v0.33.0/doc/md013.md
|
||||
MD013:
|
||||
# Number of characters
|
||||
line_length: 119
|
||||
# Number of characters for headings
|
||||
heading_line_length: 119
|
||||
# Number of characters for code blocks
|
||||
code_block_line_length: 119
|
||||
# Include code blocks
|
||||
code_blocks: true
|
||||
# Include tables
|
||||
tables: true
|
||||
# Include headings
|
||||
headings: true
|
||||
# Strict length checking
|
||||
strict: false
|
||||
# Stern length checking
|
||||
stern: false
|
||||
|
||||
# MD022/blanks-around-headings : Headings should be surrounded by blank lines : https://github.com/DavidAnson/markdownlint/blob/v0.33.0/doc/md022.md
|
||||
MD022:
|
||||
# Blank lines above heading
|
||||
lines_above: 2
|
||||
# Blank lines below heading
|
||||
lines_below: 1
|
||||
|
||||
# MD023/heading-start-left : Headings must start at the beginning of the line : https://github.com/DavidAnson/markdownlint/blob/v0.33.0/doc/md023.md
|
||||
MD023: true
|
||||
|
||||
# MD025/single-title/single-h1 : Multiple top-level headings in the same document : https://github.com/DavidAnson/markdownlint/blob/v0.33.0/doc/md025.md
|
||||
MD025:
|
||||
# Heading level
|
||||
level: 1
|
||||
# RegExp for matching title in front matter
|
||||
front_matter_title: "^\\s*title\\s*[:=]"
|
||||
|
||||
# MD026/no-trailing-punctuation : Trailing punctuation in heading : https://github.com/DavidAnson/markdownlint/blob/v0.33.0/doc/md026.md
|
||||
MD026:
|
||||
# Punctuation characters
|
||||
punctuation: ".,;:!。,;:!"
|
||||
|
||||
# MD027/no-multiple-space-blockquote : Multiple spaces after blockquote symbol : https://github.com/DavidAnson/markdownlint/blob/v0.33.0/doc/md027.md
|
||||
MD027: true
|
||||
|
||||
# MD028/no-blanks-blockquote : Blank line inside blockquote : https://github.com/DavidAnson/markdownlint/blob/v0.33.0/doc/md028.md
|
||||
MD028: true
|
||||
|
||||
# MD029/ol-prefix : Ordered list item prefix : https://github.com/DavidAnson/markdownlint/blob/v0.33.0/doc/md029.md
|
||||
MD029:
|
||||
# List style
|
||||
style: "ordered"
|
||||
|
||||
# MD031/blanks-around-fences : Fenced code blocks should be surrounded by blank lines : https://github.com/DavidAnson/markdownlint/blob/v0.33.0/doc/md031.md
|
||||
MD031:
|
||||
# Include list items
|
||||
list_items: true
|
||||
|
||||
# MD032/blanks-around-lists : Lists should be surrounded by blank lines : https://github.com/DavidAnson/markdownlint/blob/v0.33.0/doc/md032.md
|
||||
MD032: true
|
||||
|
||||
# MD034/no-bare-urls : Bare URL used : https://github.com/DavidAnson/markdownlint/blob/v0.33.0/doc/md034.md
|
||||
MD034: true
|
||||
|
||||
# MD036/no-emphasis-as-heading : Emphasis used instead of a heading : https://github.com/DavidAnson/markdownlint/blob/v0.33.0/doc/md036.md
|
||||
MD036:
|
||||
# Punctuation characters
|
||||
punctuation: ".,;:!?。,;:!?"
|
||||
|
||||
# MD037/no-space-in-emphasis : Spaces inside emphasis markers : https://github.com/DavidAnson/markdownlint/blob/v0.33.0/doc/md037.md
|
||||
MD037: true
|
||||
|
||||
# MD038/no-space-in-code : Spaces inside code span elements : https://github.com/DavidAnson/markdownlint/blob/v0.33.0/doc/md038.md
|
||||
MD038: true
|
||||
|
||||
# MD039/no-space-in-links : Spaces inside link text : https://github.com/DavidAnson/markdownlint/blob/v0.33.0/doc/md039.md
|
||||
MD039: true
|
||||
|
||||
# MD040/fenced-code-language : Fenced code blocks should have a language specified : https://github.com/DavidAnson/markdownlint/blob/v0.33.0/doc/md040.md
|
||||
MD040:
|
||||
# Require language only
|
||||
language_only: true
|
||||
|
||||
# MD041/first-line-heading/first-line-h1 : First line in a file should be a top-level heading : https://github.com/DavidAnson/markdownlint/blob/v0.33.0/doc/md041.md
|
||||
MD041:
|
||||
# Heading level
|
||||
level: 1
|
||||
# RegExp for matching title in front matter
|
||||
front_matter_title: "^\\s*title\\s*[:=]"
|
||||
|
||||
# MD042/no-empty-links : No empty links : https://github.com/DavidAnson/markdownlint/blob/v0.33.0/doc/md042.md
|
||||
MD042: true
|
||||
|
||||
# MD046/code-block-style : Code block style : https://github.com/DavidAnson/markdownlint/blob/v0.33.0/doc/md046.md
|
||||
MD046:
|
||||
# Block style
|
||||
style: "consistent"
|
||||
|
||||
# MD047/single-trailing-newline : Files should end with a single newline character : https://github.com/DavidAnson/markdownlint/blob/v0.33.0/doc/md047.md
|
||||
MD047: true
|
||||
|
||||
# MD048/code-fence-style : Code fence style : https://github.com/DavidAnson/markdownlint/blob/v0.33.0/doc/md048.md
|
||||
MD048:
|
||||
# Code fence style
|
||||
style: "consistent"
|
||||
|
||||
# MD049/emphasis-style : Emphasis style : https://github.com/DavidAnson/markdownlint/blob/v0.33.0/doc/md049.md
|
||||
MD049:
|
||||
# Emphasis style
|
||||
style: "consistent"
|
||||
|
||||
# MD050/strong-style : Strong style : https://github.com/DavidAnson/markdownlint/blob/v0.33.0/doc/md050.md
|
||||
MD050:
|
||||
# Strong style
|
||||
style: "consistent"
|
||||
|
||||
# MD051/link-fragments : Link fragments should be valid : https://github.com/DavidAnson/markdownlint/blob/v0.33.0/doc/md051.md
|
||||
MD051: true
|
||||
|
||||
# MD052/reference-links-images : Reference links and images should use a label that is defined : https://github.com/DavidAnson/markdownlint/blob/v0.33.0/doc/md052.md
|
||||
MD052:
|
||||
# Include shortcut syntax
|
||||
shortcut_syntax: false
|
||||
|
||||
# MD053/link-image-reference-definitions : Link and image reference definitions should be needed : https://github.com/DavidAnson/markdownlint/blob/v0.33.0/doc/md053.md
|
||||
MD053:
|
||||
# Ignored definitions
|
||||
ignored_definitions:
|
||||
- "//"
|
||||
|
||||
# MD054/link-image-style : Link and image style : https://github.com/DavidAnson/markdownlint/blob/v0.33.0/doc/md054.md
|
||||
MD054:
|
||||
# Allow autolinks
|
||||
autolink: true
|
||||
# Allow inline links and images
|
||||
inline: true
|
||||
# Allow full reference links and images
|
||||
full: true
|
||||
# Allow collapsed reference links and images
|
||||
collapsed: true
|
||||
# Allow shortcut reference links and images
|
||||
shortcut: true
|
||||
# Allow URLs as inline links
|
||||
url_inline: true
|
||||
|
||||
# MD055/table-pipe-style : Table pipe style : https://github.com/DavidAnson/markdownlint/blob/v0.33.0/doc/md055.md
|
||||
MD055:
|
||||
# Table pipe style
|
||||
style: "consistent"
|
||||
|
||||
# MD056/table-column-count : Table column count : https://github.com/DavidAnson/markdownlint/blob/v0.33.0/doc/md056.md
|
||||
MD056: true
|
25
.pre-commit-config.yaml
Normal file
25
.pre-commit-config.yaml
Normal file
@ -0,0 +1,25 @@
|
||||
repos:
|
||||
- repo: https://github.com/astral-sh/ruff-pre-commit
|
||||
# Ruff version.
|
||||
rev: v0.3.2
|
||||
hooks:
|
||||
# Run the linter.
|
||||
- id: ruff
|
||||
args: [ --fix ]
|
||||
# Run the formatter.
|
||||
- id: ruff-format
|
||||
|
||||
- repo: https://github.com/igorshubovych/markdownlint-cli
|
||||
rev: v0.39.0
|
||||
hooks:
|
||||
- id: markdownlint
|
||||
args: ["-f"]
|
||||
|
||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||
rev: v4.5.0
|
||||
hooks:
|
||||
- id: end-of-file-fixer
|
||||
- id: trailing-whitespace
|
||||
args: [--markdown-linebreak-ext=md]
|
||||
- id: check-merge-conflict
|
||||
- id: mixed-line-ending
|
61
CHANGELOG.md
61
CHANGELOG.md
@ -1,76 +1,101 @@
|
||||
# Change log
|
||||
|
||||
|
||||
### 0.4.0
|
||||
## 0.4.1
|
||||
|
||||
- Fixed crash when missing cli args ([#48](https://github.com/xtream1101/humblebundle-downloader/pull/48))
|
||||
- Updated the Trove url ([#59](https://github.com/xtream1101/humblebundle-downloader/pull/59))
|
||||
- Using [pre-commit](https://pre-commit.com/) hooks for formatting and linting
|
||||
- Moved from setuptools to poetry for packaging
|
||||
|
||||
|
||||
## 0.4.0
|
||||
|
||||
- Deprecate the `download` argument. It is no longer needed since that is the only action that can be taken
|
||||
|
||||
|
||||
### 0.3.4
|
||||
## 0.3.4
|
||||
|
||||
- Merged in [PR 35](https://github.com/xtream1101/humblebundle-downloader/pull/35) to fix some trove games not downloading
|
||||
|
||||
|
||||
### 0.3.3
|
||||
## 0.3.3
|
||||
|
||||
- Fixed crashing when file is missing on humblebundle
|
||||
- Updated cookie info in readme
|
||||
- Supports passing in the cookie value of `_simpleauth_sess` by using `--session-auth`
|
||||
|
||||
|
||||
### 0.3.1
|
||||
## 0.3.1
|
||||
|
||||
- Added support for netscape cookies
|
||||
|
||||
|
||||
### 0.3.0
|
||||
## 0.3.0
|
||||
|
||||
- pip install now requires python version 3.4+
|
||||
- `--trove` will only download trove products, nothing else
|
||||
- Filtering flags now work when downloading trove content
|
||||
|
||||
|
||||
### 0.2.2
|
||||
## 0.2.2
|
||||
|
||||
- Confirm the download is complete by checking the expected size to what downloaded
|
||||
- Fixed the platform filter
|
||||
|
||||
|
||||
### 0.2.1
|
||||
## 0.2.1
|
||||
|
||||
- Fixed include & exclude logic being switched in v0.2.0
|
||||
|
||||
|
||||
### 0.2.0
|
||||
## 0.2.0
|
||||
|
||||
- Added **Humble Trove** support _(`--trove` to also check/download trove content)_
|
||||
- Now by default only new content is downloaded. Use `--update` to also check for updated content
|
||||
|
||||
|
||||
### 0.1.3
|
||||
## 0.1.3
|
||||
|
||||
- Fixed re-downloading for real this time
|
||||
- Only use the url last modified time as the check for new versions
|
||||
|
||||
|
||||
### 0.1.2
|
||||
## 0.1.2
|
||||
|
||||
- Stop using md5 & sha1 hashes to check if file is unique (was creating duplicate downloads of the same file)
|
||||
- Strip periods from end of directory & file names
|
||||
- Rename older versions of a file before download the new one
|
||||
|
||||
|
||||
### 0.1.1
|
||||
## 0.1.1
|
||||
|
||||
- Delete failed downloaded files
|
||||
|
||||
|
||||
### 0.1.0
|
||||
## 0.1.0
|
||||
|
||||
- Filename saved is now the original name of the file
|
||||
- key used in cache is different due to changing the file name (this may result in duplicate downloads if you have run the older version)
|
||||
- Support for downloading a single Bundle/Purchase by using the flag `-k` or `--key` and getting the key from the url of a purchase
|
||||
- key used in cache is different due to changing the file name
|
||||
- _this may result in duplicate downloads if you have run the older version_
|
||||
- Support for downloading a single Bundle/Purchase by using the
|
||||
flag `-k` or `--key` and getting the key from the url of a purchase
|
||||
|
||||
|
||||
### 0.0.8
|
||||
## 0.0.8
|
||||
|
||||
- gen-cookies now works with SSO feature and 2FA logins
|
||||
- Added `--include` & `--exclude` cli args to filter file types
|
||||
|
||||
|
||||
### 0.0.7
|
||||
- Replace `:` with ` -` in filenames
|
||||
## 0.0.7
|
||||
|
||||
- Replace `:` with `-` in filenames
|
||||
- Ignore items that do not have a web url
|
||||
|
||||
|
||||
### 0.0.6
|
||||
## 0.0.6
|
||||
|
||||
- Started change log
|
||||
- Added more detail to readme
|
||||
- Removed the use of f-strings to support more python versions
|
||||
|
30
README.md
30
README.md
@ -1,13 +1,16 @@
|
||||
# Humble Bundle Downloader
|
||||
|
||||
[![PyPI](https://img.shields.io/pypi/v/humblebundle-downloader.svg)](https://pypi.python.org/pypi/humblebundle-downloader)
|
||||
[![PyPI](https://img.shields.io/pypi/l/humblebundle-downloader.svg)](https://pypi.python.org/pypi/humblebundle-downloader)
|
||||
|
||||
|
||||
**Download all of your content from your Humble Bundle Library!**
|
||||
|
||||
The first time this runs it may take a while because it will download everything. After that it will only download the content that has been updated or is missing.
|
||||
The first time this runs it may take a while because it will download everything.
|
||||
After that it will only download the content that has been updated or is missing.
|
||||
|
||||
|
||||
## Features
|
||||
|
||||
- support for Humble Trove _(`--trove` flag)_
|
||||
- downloads new and updated content from your Humble Bundle Library on each run _(only check for updates if using `--update`)_
|
||||
- cli command for easy use (downloading will also work on a headless system)
|
||||
@ -18,23 +21,29 @@ The first time this runs it may take a while because it will download everything
|
||||
|
||||
|
||||
## Install
|
||||
|
||||
`pip install humblebundle-downloader`
|
||||
|
||||
|
||||
## Instructions
|
||||
|
||||
|
||||
### 1. Getting cookies
|
||||
First thing to do is get your account cookies. This can be done by getting a browser extension that lets you see or export your cookies.
|
||||
|
||||
First thing to do is get your account cookies.
|
||||
This can be done by getting a browser extension that lets you see or export your cookies.
|
||||
|
||||
- **Method 1 (recommended)**
|
||||
- Get the value of the cookie called `_simpleauth_sess` and pass that value using `-s "COOKIE_VALUE"`
|
||||
|
||||
- **Method 2**
|
||||
- Export the cookies in the Netscape format using an extension.
|
||||
If your exported cookie file is not working, it may be a formatting issue, this can be fixed by running the command `curl -b cookies.orig.txt --cookie-jar cookies.txt http://bogus`
|
||||
If your exported cookie file is not working, it may be a formatting issue.
|
||||
This can be fixed by running the command `curl -b cookies.orig.txt --cookie-jar cookies.txt http://bogus`
|
||||
|
||||
|
||||
### 2. Downloading your library
|
||||
|
||||
Use the following command to download your Humble Bundle Library:
|
||||
`hbd --cookie-file cookies.txt --library-path "Downloaded Library" --progress`
|
||||
|
||||
@ -43,7 +52,12 @@ This directory structure will be used:
|
||||
|
||||
|
||||
## Notes
|
||||
* Inside your library folder a file named `.cache.json` is saved and keeps track of the files that have been downloaded. This way running the download command again pointing to the same directory will only download new or updated files.
|
||||
* Use `--help` with all `hbd` commands to see available options
|
||||
* Find supported platforms for the `--platform` flag by visiting your Humble Bundle Library and look under the **Platform** dropdown
|
||||
* Download select bundles by using the `-k` or `--keys` flag. Find these keys by going to your *Purchases* section, click on a products and there should be a `downloads?key=XXXX` in the url.
|
||||
|
||||
- Inside your library folder a file named `.cache.json` is saved and keeps track of the files that have been downloaded.
|
||||
This way running the download command again pointing to the same directory will only download new or updated files.
|
||||
- Use `--help` with all `hbd` commands to see available options
|
||||
- Find supported platforms for the `--platform` flag by visiting your Humble Bundle Library
|
||||
and look under the **Platform** dropdown
|
||||
- Download select bundles by using the `-k` or `--keys` flag.
|
||||
Find these keys by going to your _Purchases_ section,
|
||||
click on a products and there should be a `downloads?key=XXXX` in the url.
|
||||
|
@ -1 +0,0 @@
|
||||
__version__ = '0.4.0'
|
@ -5,17 +5,17 @@ import argparse
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
LOG_LEVEL = os.environ.get('HBD_LOGLEVEL', 'INFO').upper()
|
||||
LOG_LEVEL = os.environ.get("HBD_LOGLEVEL", "INFO").upper()
|
||||
logging.basicConfig(
|
||||
level=LOG_LEVEL,
|
||||
format='%(message)s',
|
||||
format="%(message)s",
|
||||
)
|
||||
# Ignore unwanted logs from the requests lib when debuging
|
||||
logging.getLogger('urllib3.connectionpool').setLevel(logging.WARNING)
|
||||
logging.getLogger("urllib3.connectionpool").setLevel(logging.WARNING)
|
||||
|
||||
|
||||
def parse_args(args):
|
||||
if len(args) > 0 and args[0].lower() == 'download':
|
||||
if len(args) > 0 and args[0].lower() == "download":
|
||||
args = args[1:]
|
||||
raise DeprecationWarning("`download` argument is no longer used")
|
||||
|
||||
@ -23,55 +23,75 @@ def parse_args(args):
|
||||
|
||||
cookie = parser.add_mutually_exclusive_group(required=True)
|
||||
cookie.add_argument(
|
||||
'-c', '--cookie-file', type=str,
|
||||
"-c",
|
||||
"--cookie-file",
|
||||
type=str,
|
||||
help="Location of the cookies file",
|
||||
)
|
||||
cookie.add_argument(
|
||||
'-s', '--session-auth', type=str,
|
||||
"-s",
|
||||
"--session-auth",
|
||||
type=str,
|
||||
help="Value of the cookie _simpleauth_sess. WRAP IN QUOTES",
|
||||
)
|
||||
parser.add_argument(
|
||||
'-l', '--library-path', type=str,
|
||||
"-l",
|
||||
"--library-path",
|
||||
type=str,
|
||||
help="Folder to download all content to",
|
||||
required=True,
|
||||
)
|
||||
parser.add_argument(
|
||||
'-t', '--trove', action='store_true',
|
||||
"-t",
|
||||
"--trove",
|
||||
action="store_true",
|
||||
help="Only check and download Humble Trove content",
|
||||
)
|
||||
parser.add_argument(
|
||||
'-u', '--update', action='store_true',
|
||||
help=("Check to see if products have been updated "
|
||||
"(still get new products)"),
|
||||
"-u",
|
||||
"--update",
|
||||
action="store_true",
|
||||
help=("Check to see if products have been updated " "(still get new products)"),
|
||||
)
|
||||
parser.add_argument(
|
||||
'-p', '--platform',
|
||||
type=str, nargs='*',
|
||||
help=("Only get content in a platform. Values can be seen in your "
|
||||
"humble bundle's library dropdown. Ex: -p ebook video"),
|
||||
"-p",
|
||||
"--platform",
|
||||
type=str,
|
||||
nargs="*",
|
||||
help=(
|
||||
"Only get content in a platform. Values can be seen in your "
|
||||
"humble bundle's library dropdown. Ex: -p ebook video"
|
||||
),
|
||||
)
|
||||
parser.add_argument(
|
||||
'--progress',
|
||||
action='store_true',
|
||||
"--progress",
|
||||
action="store_true",
|
||||
help="Display progress bar for downloads",
|
||||
)
|
||||
filter_ext = parser.add_mutually_exclusive_group()
|
||||
filter_ext.add_argument(
|
||||
'-e', '--exclude',
|
||||
type=str, nargs='*',
|
||||
help=("File extensions to ignore when downloading files. "
|
||||
"Ex: -e pdf mobi"),
|
||||
"-e",
|
||||
"--exclude",
|
||||
type=str,
|
||||
nargs="*",
|
||||
help=("File extensions to ignore when downloading files. " "Ex: -e pdf mobi"),
|
||||
)
|
||||
filter_ext.add_argument(
|
||||
'-i', '--include',
|
||||
type=str, nargs='*',
|
||||
"-i",
|
||||
"--include",
|
||||
type=str,
|
||||
nargs="*",
|
||||
help="Only download files with these extensions. Ex: -i pdf mobi",
|
||||
)
|
||||
parser.add_argument(
|
||||
'-k', '--keys',
|
||||
type=str, nargs='*',
|
||||
help=("The purchase download key. Find in the url on the "
|
||||
"products/bundle download page. Can set multiple"),
|
||||
"-k",
|
||||
"--keys",
|
||||
type=str,
|
||||
nargs="*",
|
||||
help=(
|
||||
"The purchase download key. Find in the url on the "
|
||||
"products/bundle download page. Can set multiple"
|
||||
),
|
||||
)
|
||||
|
||||
return parser.parse_args(args)
|
||||
@ -81,6 +101,7 @@ def cli():
|
||||
cli_args = parse_args(sys.argv[1:])
|
||||
|
||||
from .download_library import DownloadLibrary
|
||||
|
||||
DownloadLibrary(
|
||||
cli_args.library_path,
|
||||
cookie_path=cli_args.cookie_file,
|
||||
|
@ -12,27 +12,39 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def _clean_name(dirty_str):
|
||||
allowed_chars = (' ', '_', '.', '-', '[', ']')
|
||||
allowed_chars = (" ", "_", ".", "-", "[", "]")
|
||||
clean = []
|
||||
for c in dirty_str.replace('+', '_').replace(':', ' -'):
|
||||
for c in dirty_str.replace("+", "_").replace(":", " -"):
|
||||
if c.isalpha() or c.isdigit() or c in allowed_chars:
|
||||
clean.append(c)
|
||||
|
||||
return "".join(clean).strip().rstrip('.')
|
||||
return "".join(clean).strip().rstrip(".")
|
||||
|
||||
|
||||
class DownloadLibrary:
|
||||
|
||||
def __init__(self, library_path, cookie_path=None, cookie_auth=None,
|
||||
progress_bar=False, ext_include=None, ext_exclude=None,
|
||||
platform_include=None, purchase_keys=None, trove=False,
|
||||
update=False):
|
||||
def __init__(
|
||||
self,
|
||||
library_path,
|
||||
cookie_path=None,
|
||||
cookie_auth=None,
|
||||
progress_bar=False,
|
||||
ext_include=None,
|
||||
ext_exclude=None,
|
||||
platform_include=None,
|
||||
purchase_keys=None,
|
||||
trove=False,
|
||||
update=False,
|
||||
):
|
||||
self.library_path = library_path
|
||||
self.progress_bar = progress_bar
|
||||
self.ext_include = [] if ext_include is None else list(map(str.lower, ext_include)) # noqa: E501
|
||||
self.ext_exclude = [] if ext_exclude is None else list(map(str.lower, ext_exclude)) # noqa: E501
|
||||
self.ext_include = (
|
||||
[] if ext_include is None else list(map(str.lower, ext_include))
|
||||
)
|
||||
self.ext_exclude = (
|
||||
[] if ext_exclude is None else list(map(str.lower, ext_exclude))
|
||||
)
|
||||
|
||||
if platform_include is None or 'all' in platform_include:
|
||||
if platform_include is None or "all" in platform_include:
|
||||
# if 'all', then do not need to use this check
|
||||
platform_include = []
|
||||
self.platform_include = list(map(str.lower, platform_include))
|
||||
@ -49,23 +61,24 @@ class DownloadLibrary:
|
||||
self.session.cookies = cookie_jar
|
||||
except http.cookiejar.LoadError:
|
||||
# Still support the original cookie method
|
||||
with open(cookie_path, 'r') as f:
|
||||
self.session.headers.update({'cookie': f.read().strip()})
|
||||
with open(cookie_path, "r") as f:
|
||||
self.session.headers.update({"cookie": f.read().strip()})
|
||||
elif cookie_auth:
|
||||
self.session.headers.update(
|
||||
{'cookie': '_simpleauth_sess={}'.format(cookie_auth)}
|
||||
{"cookie": "_simpleauth_sess={}".format(cookie_auth)}
|
||||
)
|
||||
|
||||
def start(self):
|
||||
|
||||
self.cache_file = os.path.join(self.library_path, '.cache.json')
|
||||
self.cache_file = os.path.join(self.library_path, ".cache.json")
|
||||
self.cache_data = self._load_cache_data(self.cache_file)
|
||||
self.purchase_keys = self.purchase_keys if self.purchase_keys else self._get_purchase_keys() # noqa: E501
|
||||
self.purchase_keys = (
|
||||
self.purchase_keys if self.purchase_keys else self._get_purchase_keys()
|
||||
)
|
||||
|
||||
if self.trove is True:
|
||||
logger.info("Only checking the Humble Trove...")
|
||||
for product in self._get_trove_products():
|
||||
title = _clean_name(product['human-name'])
|
||||
title = _clean_name(product["human-name"])
|
||||
self._process_trove_product(title, product)
|
||||
else:
|
||||
for order_id in self.purchase_keys:
|
||||
@ -74,50 +87,56 @@ class DownloadLibrary:
|
||||
def _get_trove_download_url(self, machine_name, web_name):
|
||||
try:
|
||||
sign_r = self.session.post(
|
||||
'https://www.humblebundle.com/api/v1/user/download/sign',
|
||||
"https://www.humblebundle.com/api/v1/user/download/sign",
|
||||
data={
|
||||
'machine_name': machine_name,
|
||||
'filename': web_name,
|
||||
"machine_name": machine_name,
|
||||
"filename": web_name,
|
||||
},
|
||||
)
|
||||
except Exception:
|
||||
logger.error("Failed to get download url for trove product {title}"
|
||||
.format(title=web_name))
|
||||
logger.error(
|
||||
"Failed to get download url for trove product {title}".format(
|
||||
title=web_name
|
||||
)
|
||||
)
|
||||
return None
|
||||
|
||||
logger.debug("Signed url response {sign_r}".format(sign_r=sign_r))
|
||||
if sign_r.json().get('_errors') == 'Unauthorized':
|
||||
if sign_r.json().get("_errors") == "Unauthorized":
|
||||
logger.critical("Your account does not have access to the Trove")
|
||||
sys.exit()
|
||||
signed_url = sign_r.json()['signed_url']
|
||||
signed_url = sign_r.json()["signed_url"]
|
||||
logger.debug("Signed url {signed_url}".format(signed_url=signed_url))
|
||||
return signed_url
|
||||
|
||||
def _process_trove_product(self, title, product):
|
||||
for platform, download in product['downloads'].items():
|
||||
for platform, download in product["downloads"].items():
|
||||
# Sometimes the name has a dir in it
|
||||
# Example is "Broken Sword 5 - the Serpent's Curse"
|
||||
# Only the windows file has a dir like
|
||||
# "revolutionsoftware/BS5_v2.2.1-win32.zip"
|
||||
if self._should_download_platform(platform) is False: # noqa: E501
|
||||
logger.info("Skipping {platform} for {product_title}"
|
||||
.format(platform=platform,
|
||||
product_title=title))
|
||||
if self._should_download_platform(platform) is False:
|
||||
logger.info(
|
||||
"Skipping {platform} for {product_title}".format(
|
||||
platform=platform, product_title=title
|
||||
)
|
||||
)
|
||||
continue
|
||||
|
||||
web_name = download['url']['web'].split('/')[-1]
|
||||
ext = web_name.split('.')[-1]
|
||||
web_name = download["url"]["web"].split("/")[-1]
|
||||
ext = web_name.split(".")[-1]
|
||||
if self._should_download_file_type(ext) is False:
|
||||
logger.info("Skipping the file {web_name}"
|
||||
.format(web_name=web_name))
|
||||
logger.info("Skipping the file {web_name}".format(web_name=web_name))
|
||||
continue
|
||||
|
||||
cache_file_key = 'trove:{name}'.format(name=web_name)
|
||||
cache_file_key = "trove:{name}".format(name=web_name)
|
||||
file_info = {
|
||||
'uploaded_at': (download.get('uploaded_at')
|
||||
or download.get('timestamp')
|
||||
or product.get('date_added', '0')),
|
||||
'md5': download.get('md5', 'UNKNOWN_MD5'),
|
||||
"uploaded_at": (
|
||||
download.get("uploaded_at")
|
||||
or download.get("timestamp")
|
||||
or product.get("date_added", "0")
|
||||
),
|
||||
"md5": download.get("md5", "UNKNOWN_MD5"),
|
||||
}
|
||||
cache_file_info = self.cache_data.get(cache_file_key, {})
|
||||
|
||||
@ -125,20 +144,21 @@ class DownloadLibrary:
|
||||
# Do not care about checking for updates at this time
|
||||
continue
|
||||
|
||||
if (file_info['uploaded_at'] != cache_file_info.get('uploaded_at')
|
||||
and file_info['md5'] != cache_file_info.get('md5')):
|
||||
product_folder = os.path.join(
|
||||
self.library_path, 'Humble Trove', title
|
||||
)
|
||||
if file_info["uploaded_at"] != cache_file_info.get(
|
||||
"uploaded_at"
|
||||
) and file_info["md5"] != cache_file_info.get("md5"):
|
||||
product_folder = os.path.join(self.library_path, "Humble Trove", title)
|
||||
# Create directory to save the files to
|
||||
try: os.makedirs(product_folder) # noqa: E701
|
||||
except OSError: pass # noqa: E701
|
||||
try:
|
||||
os.makedirs(product_folder)
|
||||
except OSError:
|
||||
pass
|
||||
local_filename = os.path.join(
|
||||
product_folder,
|
||||
web_name,
|
||||
)
|
||||
signed_url = self._get_trove_download_url(
|
||||
download['machine_name'],
|
||||
download["machine_name"],
|
||||
web_name,
|
||||
)
|
||||
if signed_url is None:
|
||||
@ -148,14 +168,14 @@ class DownloadLibrary:
|
||||
try:
|
||||
product_r = self.session.get(signed_url, stream=True)
|
||||
except Exception:
|
||||
logger.error("Failed to get trove product {title}"
|
||||
.format(title=web_name))
|
||||
logger.error(
|
||||
"Failed to get trove product {title}".format(title=web_name)
|
||||
)
|
||||
continue
|
||||
|
||||
if 'uploaded_at' in cache_file_info:
|
||||
if "uploaded_at" in cache_file_info:
|
||||
uploaded_at = time.strftime(
|
||||
'%Y-%m-%d',
|
||||
time.localtime(int(cache_file_info['uploaded_at']))
|
||||
"%Y-%m-%d", time.localtime(int(cache_file_info["uploaded_at"]))
|
||||
)
|
||||
else:
|
||||
uploaded_at = None
|
||||
@ -171,10 +191,11 @@ class DownloadLibrary:
|
||||
def _get_trove_products(self):
|
||||
trove_products = []
|
||||
idx = 0
|
||||
trove_base_url = 'https://www.humblebundle.com/client/catalog?index={idx}' # noqa: E501
|
||||
trove_base_url = "https://www.humblebundle.com/client/catalog?index={idx}"
|
||||
while True:
|
||||
logger.debug("Collecting trove product data from api pg:{idx} ..."
|
||||
.format(idx=idx))
|
||||
logger.debug(
|
||||
"Collecting trove product data from api pg:{idx} ...".format(idx=idx)
|
||||
)
|
||||
trove_page_url = trove_base_url.format(idx=idx)
|
||||
try:
|
||||
trove_r = self.session.get(trove_page_url)
|
||||
@ -193,72 +214,80 @@ class DownloadLibrary:
|
||||
return trove_products
|
||||
|
||||
def _process_order_id(self, order_id):
|
||||
order_url = 'https://www.humblebundle.com/api/v1/order/{order_id}?all_tpkds=true'.format(order_id=order_id) # noqa: E501
|
||||
order_url = "https://www.humblebundle.com/api/v1/order/{order_id}?all_tpkds=true".format(
|
||||
order_id=order_id
|
||||
)
|
||||
try:
|
||||
order_r = self.session.get(
|
||||
order_url,
|
||||
headers={
|
||||
'content-type': 'application/json',
|
||||
'content-encoding': 'gzip',
|
||||
"content-type": "application/json",
|
||||
"content-encoding": "gzip",
|
||||
},
|
||||
)
|
||||
except Exception:
|
||||
logger.error("Failed to get order key {order_id}"
|
||||
.format(order_id=order_id))
|
||||
logger.error("Failed to get order key {order_id}".format(order_id=order_id))
|
||||
return
|
||||
|
||||
logger.debug("Order request: {order_r}".format(order_r=order_r))
|
||||
order = order_r.json()
|
||||
bundle_title = _clean_name(order['product']['human_name'])
|
||||
bundle_title = _clean_name(order["product"]["human_name"])
|
||||
logger.info("Checking bundle: " + str(bundle_title))
|
||||
for product in order['subproducts']:
|
||||
for product in order["subproducts"]:
|
||||
self._process_product(order_id, bundle_title, product)
|
||||
|
||||
def _rename_old_file(self, local_filename, append_str):
|
||||
# Check if older file exists, if so rename
|
||||
if os.path.isfile(local_filename) is True:
|
||||
filename_parts = local_filename.rsplit('.', 1)
|
||||
new_name = "{name}_{append_str}.{ext}"\
|
||||
.format(name=filename_parts[0],
|
||||
append_str=append_str,
|
||||
ext=filename_parts[1])
|
||||
filename_parts = local_filename.rsplit(".", 1)
|
||||
new_name = "{name}_{append_str}.{ext}".format(
|
||||
name=filename_parts[0], append_str=append_str, ext=filename_parts[1]
|
||||
)
|
||||
os.rename(local_filename, new_name)
|
||||
logger.info("Renamed older file to {new_name}"
|
||||
.format(new_name=new_name))
|
||||
logger.info("Renamed older file to {new_name}".format(new_name=new_name))
|
||||
|
||||
def _process_product(self, order_id, bundle_title, product):
|
||||
product_title = _clean_name(product['human_name'])
|
||||
product_title = _clean_name(product["human_name"])
|
||||
# Get all types of download for a product
|
||||
for download_type in product['downloads']:
|
||||
if self._should_download_platform(download_type['platform']) is False: # noqa: E501
|
||||
logger.info("Skipping {platform} for {product_title}"
|
||||
.format(platform=download_type['platform'],
|
||||
product_title=product_title))
|
||||
for download_type in product["downloads"]:
|
||||
if self._should_download_platform(download_type["platform"]) is False:
|
||||
logger.info(
|
||||
"Skipping {platform} for {product_title}".format(
|
||||
platform=download_type["platform"], product_title=product_title
|
||||
)
|
||||
)
|
||||
continue
|
||||
|
||||
product_folder = os.path.join(
|
||||
self.library_path, bundle_title, product_title
|
||||
)
|
||||
# Create directory to save the files to
|
||||
try: os.makedirs(product_folder) # noqa: E701
|
||||
except OSError: pass # noqa: E701
|
||||
try:
|
||||
os.makedirs(product_folder)
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
# Download each file type of a product
|
||||
for file_type in download_type['download_struct']:
|
||||
for file_type in download_type["download_struct"]:
|
||||
try:
|
||||
url = file_type['url']['web']
|
||||
url = file_type["url"]["web"]
|
||||
except KeyError:
|
||||
logger.info("No url found: {bundle_title}/{product_title}"
|
||||
.format(bundle_title=bundle_title,
|
||||
product_title=product_title))
|
||||
logger.info(
|
||||
"No url found: {bundle_title}/{product_title}".format(
|
||||
bundle_title=bundle_title, product_title=product_title
|
||||
)
|
||||
)
|
||||
continue
|
||||
|
||||
url_filename = url.split('?')[0].split('/')[-1]
|
||||
cache_file_key = order_id + ':' + url_filename
|
||||
ext = url_filename.split('.')[-1]
|
||||
url_filename = url.split("?")[0].split("/")[-1]
|
||||
cache_file_key = order_id + ":" + url_filename
|
||||
ext = url_filename.split(".")[-1]
|
||||
if self._should_download_file_type(ext) is False:
|
||||
logger.info("Skipping the file {url_filename}"
|
||||
.format(url_filename=url_filename))
|
||||
logger.info(
|
||||
"Skipping the file {url_filename}".format(
|
||||
url_filename=url_filename
|
||||
)
|
||||
)
|
||||
continue
|
||||
|
||||
local_filename = os.path.join(product_folder, url_filename)
|
||||
@ -277,23 +306,30 @@ class DownloadLibrary:
|
||||
# Check to see if the file still exists
|
||||
if product_r.status_code != 200:
|
||||
logger.debug(
|
||||
"File missing for {bundle_title}/{product_title}: {url}"
|
||||
.format(bundle_title=bundle_title,
|
||||
"File missing for {bundle_title}/{product_title}: {url}".format(
|
||||
bundle_title=bundle_title,
|
||||
product_title=product_title,
|
||||
url=url))
|
||||
url=url,
|
||||
)
|
||||
)
|
||||
continue
|
||||
|
||||
logger.debug("Item request: {product_r}, Url: {url}"
|
||||
.format(product_r=product_r, url=url))
|
||||
logger.debug(
|
||||
"Item request: {product_r}, Url: {url}".format(
|
||||
product_r=product_r, url=url
|
||||
)
|
||||
)
|
||||
file_info = {
|
||||
'url_last_modified': product_r.headers['Last-Modified'],
|
||||
"url_last_modified": product_r.headers["Last-Modified"],
|
||||
}
|
||||
if file_info['url_last_modified'] != cache_file_info.get('url_last_modified'): # noqa: E501
|
||||
if 'url_last_modified' in cache_file_info:
|
||||
if file_info["url_last_modified"] != cache_file_info.get(
|
||||
"url_last_modified"
|
||||
):
|
||||
if "url_last_modified" in cache_file_info:
|
||||
last_modified = datetime.datetime.strptime(
|
||||
cache_file_info['url_last_modified'],
|
||||
'%a, %d %b %Y %H:%M:%S %Z'
|
||||
).strftime('%Y-%m-%d')
|
||||
cache_file_info["url_last_modified"],
|
||||
"%a, %d %b %Y %H:%M:%S %Z",
|
||||
).strftime("%Y-%m-%d")
|
||||
else:
|
||||
last_modified = None
|
||||
self._process_download(
|
||||
@ -310,14 +346,17 @@ class DownloadLibrary:
|
||||
# quits it can keep track of the progress
|
||||
# Note: Only safe because of single thread,
|
||||
# need to change if refactor to multi threading
|
||||
with open(self.cache_file, 'w') as outfile:
|
||||
with open(self.cache_file, "w") as outfile:
|
||||
json.dump(
|
||||
self.cache_data, outfile,
|
||||
sort_keys=True, indent=4,
|
||||
self.cache_data,
|
||||
outfile,
|
||||
sort_keys=True,
|
||||
indent=4,
|
||||
)
|
||||
|
||||
def _process_download(self, open_r, cache_file_key, file_info,
|
||||
local_filename, rename_str=None):
|
||||
def _process_download(
|
||||
self, open_r, cache_file_key, file_info, local_filename, rename_str=None
|
||||
):
|
||||
try:
|
||||
if rename_str:
|
||||
self._rename_old_file(local_filename, rename_str)
|
||||
@ -328,14 +367,19 @@ class DownloadLibrary:
|
||||
if self.progress_bar:
|
||||
# Do not overwrite the progress bar on next print
|
||||
print()
|
||||
logger.error("Failed to download file {local_filename}"
|
||||
.format(local_filename=local_filename))
|
||||
logger.error(
|
||||
"Failed to download file {local_filename}".format(
|
||||
local_filename=local_filename
|
||||
)
|
||||
)
|
||||
|
||||
# Clean up broken downloaded file
|
||||
try: os.remove(local_filename) # noqa: E701
|
||||
except OSError: pass # noqa: E701
|
||||
try:
|
||||
os.remove(local_filename)
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
if type(e).__name__ == 'KeyboardInterrupt':
|
||||
if type(e).__name__ == "KeyboardInterrupt":
|
||||
sys.exit()
|
||||
|
||||
else:
|
||||
@ -349,11 +393,12 @@ class DownloadLibrary:
|
||||
open_r.connection.close()
|
||||
|
||||
def _download_file(self, product_r, local_filename):
|
||||
logger.info("Downloading: {local_filename}"
|
||||
.format(local_filename=local_filename))
|
||||
logger.info(
|
||||
"Downloading: {local_filename}".format(local_filename=local_filename)
|
||||
)
|
||||
|
||||
with open(local_filename, 'wb') as outfile:
|
||||
total_length = product_r.headers.get('content-length')
|
||||
with open(local_filename, "wb") as outfile:
|
||||
total_length = product_r.headers.get("content-length")
|
||||
if total_length is None: # no content length header
|
||||
outfile.write(product_r.content)
|
||||
else:
|
||||
@ -365,18 +410,21 @@ class DownloadLibrary:
|
||||
pb_width = 50
|
||||
done = int(pb_width * dl / total_length)
|
||||
if self.progress_bar:
|
||||
print("\t{percent}% [{filler}{space}]"
|
||||
.format(percent=int(done * (100 / pb_width)),
|
||||
filler='=' * done,
|
||||
space=' ' * (pb_width - done),
|
||||
), end='\r')
|
||||
print(
|
||||
"\t{percent}% [{filler}{space}]".format(
|
||||
percent=int(done * (100 / pb_width)),
|
||||
filler="=" * done,
|
||||
space=" " * (pb_width - done),
|
||||
),
|
||||
end="\r",
|
||||
)
|
||||
|
||||
if dl != total_length:
|
||||
raise ValueError("Download did not complete")
|
||||
|
||||
def _load_cache_data(self, cache_file):
|
||||
try:
|
||||
with open(cache_file, 'r') as f:
|
||||
with open(cache_file, "r") as f:
|
||||
cache_data = json.load(f)
|
||||
except FileNotFoundError:
|
||||
cache_data = {}
|
||||
@ -385,18 +433,20 @@ class DownloadLibrary:
|
||||
|
||||
def _get_purchase_keys(self):
|
||||
try:
|
||||
library_r = self.session.get('https://www.humblebundle.com/home/library') # noqa: E501
|
||||
library_r = self.session.get("https://www.humblebundle.com/home/library")
|
||||
except Exception:
|
||||
logger.exception("Failed to get list of purchases")
|
||||
return []
|
||||
|
||||
logger.debug("Library request: " + str(library_r))
|
||||
library_page = parsel.Selector(text=library_r.text)
|
||||
user_data = library_page.css('#user-home-json-data').xpath('string()').extract_first() # noqa: E501
|
||||
user_data = (
|
||||
library_page.css("#user-home-json-data").xpath("string()").extract_first()
|
||||
)
|
||||
if user_data is None:
|
||||
raise Exception("Unable to download user-data, cookies missing?")
|
||||
orders_json = json.loads(user_data)
|
||||
return orders_json['gamekeys']
|
||||
return orders_json["gamekeys"]
|
||||
|
||||
def _should_download_platform(self, platform):
|
||||
platform = platform.lower()
|
||||
|
469
poetry.lock
generated
Normal file
469
poetry.lock
generated
Normal file
@ -0,0 +1,469 @@
|
||||
# This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand.
|
||||
|
||||
[[package]]
|
||||
name = "certifi"
|
||||
version = "2024.7.4"
|
||||
description = "Python package for providing Mozilla's CA Bundle."
|
||||
optional = false
|
||||
python-versions = ">=3.6"
|
||||
files = [
|
||||
{file = "certifi-2024.7.4-py3-none-any.whl", hash = "sha256:c198e21b1289c2ab85ee4e67bb4b4ef3ead0892059901a8d5b622f24a1101e90"},
|
||||
{file = "certifi-2024.7.4.tar.gz", hash = "sha256:5a1e7645bc0ec61a09e26c36f6106dd4cf40c6db3a1fb6352b0244e7fb057c7b"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "charset-normalizer"
|
||||
version = "3.3.2"
|
||||
description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet."
|
||||
optional = false
|
||||
python-versions = ">=3.7.0"
|
||||
files = [
|
||||
{file = "charset-normalizer-3.3.2.tar.gz", hash = "sha256:f30c3cb33b24454a82faecaf01b19c18562b1e89558fb6c56de4d9118a032fd5"},
|
||||
{file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:25baf083bf6f6b341f4121c2f3c548875ee6f5339300e08be3f2b2ba1721cdd3"},
|
||||
{file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:06435b539f889b1f6f4ac1758871aae42dc3a8c0e24ac9e60c2384973ad73027"},
|
||||
{file = "charset_normalizer-3.3.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9063e24fdb1e498ab71cb7419e24622516c4a04476b17a2dab57e8baa30d6e03"},
|
||||
{file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6897af51655e3691ff853668779c7bad41579facacf5fd7253b0133308cf000d"},
|
||||
{file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1d3193f4a680c64b4b6a9115943538edb896edc190f0b222e73761716519268e"},
|
||||
{file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cd70574b12bb8a4d2aaa0094515df2463cb429d8536cfb6c7ce983246983e5a6"},
|
||||
{file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8465322196c8b4d7ab6d1e049e4c5cb460d0394da4a27d23cc242fbf0034b6b5"},
|
||||
{file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a9a8e9031d613fd2009c182b69c7b2c1ef8239a0efb1df3f7c8da66d5dd3d537"},
|
||||
{file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:beb58fe5cdb101e3a055192ac291b7a21e3b7ef4f67fa1d74e331a7f2124341c"},
|
||||
{file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e06ed3eb3218bc64786f7db41917d4e686cc4856944f53d5bdf83a6884432e12"},
|
||||
{file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:2e81c7b9c8979ce92ed306c249d46894776a909505d8f5a4ba55b14206e3222f"},
|
||||
{file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:572c3763a264ba47b3cf708a44ce965d98555f618ca42c926a9c1616d8f34269"},
|
||||
{file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fd1abc0d89e30cc4e02e4064dc67fcc51bd941eb395c502aac3ec19fab46b519"},
|
||||
{file = "charset_normalizer-3.3.2-cp310-cp310-win32.whl", hash = "sha256:3d47fa203a7bd9c5b6cee4736ee84ca03b8ef23193c0d1ca99b5089f72645c73"},
|
||||
{file = "charset_normalizer-3.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:10955842570876604d404661fbccbc9c7e684caf432c09c715ec38fbae45ae09"},
|
||||
{file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:802fe99cca7457642125a8a88a084cef28ff0cf9407060f7b93dca5aa25480db"},
|
||||
{file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:573f6eac48f4769d667c4442081b1794f52919e7edada77495aaed9236d13a96"},
|
||||
{file = "charset_normalizer-3.3.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e"},
|
||||
{file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f27273b60488abe721a075bcca6d7f3964f9f6f067c8c4c605743023d7d3944f"},
|
||||
{file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ceae2f17a9c33cb48e3263960dc5fc8005351ee19db217e9b1bb15d28c02574"},
|
||||
{file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:65f6f63034100ead094b8744b3b97965785388f308a64cf8d7c34f2f2e5be0c4"},
|
||||
{file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:753f10e867343b4511128c6ed8c82f7bec3bd026875576dfd88483c5c73b2fd8"},
|
||||
{file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4a78b2b446bd7c934f5dcedc588903fb2f5eec172f3d29e52a9096a43722adfc"},
|
||||
{file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e537484df0d8f426ce2afb2d0f8e1c3d0b114b83f8850e5f2fbea0e797bd82ae"},
|
||||
{file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:eb6904c354526e758fda7167b33005998fb68c46fbc10e013ca97f21ca5c8887"},
|
||||
{file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:deb6be0ac38ece9ba87dea880e438f25ca3eddfac8b002a2ec3d9183a454e8ae"},
|
||||
{file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:4ab2fe47fae9e0f9dee8c04187ce5d09f48eabe611be8259444906793ab7cbce"},
|
||||
{file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:80402cd6ee291dcb72644d6eac93785fe2c8b9cb30893c1af5b8fdd753b9d40f"},
|
||||
{file = "charset_normalizer-3.3.2-cp311-cp311-win32.whl", hash = "sha256:7cd13a2e3ddeed6913a65e66e94b51d80a041145a026c27e6bb76c31a853c6ab"},
|
||||
{file = "charset_normalizer-3.3.2-cp311-cp311-win_amd64.whl", hash = "sha256:663946639d296df6a2bb2aa51b60a2454ca1cb29835324c640dafb5ff2131a77"},
|
||||
{file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0b2b64d2bb6d3fb9112bafa732def486049e63de9618b5843bcdd081d8144cd8"},
|
||||
{file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:ddbb2551d7e0102e7252db79ba445cdab71b26640817ab1e3e3648dad515003b"},
|
||||
{file = "charset_normalizer-3.3.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:55086ee1064215781fff39a1af09518bc9255b50d6333f2e4c74ca09fac6a8f6"},
|
||||
{file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8f4a014bc36d3c57402e2977dada34f9c12300af536839dc38c0beab8878f38a"},
|
||||
{file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a10af20b82360ab00827f916a6058451b723b4e65030c5a18577c8b2de5b3389"},
|
||||
{file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8d756e44e94489e49571086ef83b2bb8ce311e730092d2c34ca8f7d925cb20aa"},
|
||||
{file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:90d558489962fd4918143277a773316e56c72da56ec7aa3dc3dbbe20fdfed15b"},
|
||||
{file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6ac7ffc7ad6d040517be39eb591cac5ff87416c2537df6ba3cba3bae290c0fed"},
|
||||
{file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:7ed9e526742851e8d5cc9e6cf41427dfc6068d4f5a3bb03659444b4cabf6bc26"},
|
||||
{file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:8bdb58ff7ba23002a4c5808d608e4e6c687175724f54a5dade5fa8c67b604e4d"},
|
||||
{file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:6b3251890fff30ee142c44144871185dbe13b11bab478a88887a639655be1068"},
|
||||
{file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:b4a23f61ce87adf89be746c8a8974fe1c823c891d8f86eb218bb957c924bb143"},
|
||||
{file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:efcb3f6676480691518c177e3b465bcddf57cea040302f9f4e6e191af91174d4"},
|
||||
{file = "charset_normalizer-3.3.2-cp312-cp312-win32.whl", hash = "sha256:d965bba47ddeec8cd560687584e88cf699fd28f192ceb452d1d7ee807c5597b7"},
|
||||
{file = "charset_normalizer-3.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:96b02a3dc4381e5494fad39be677abcb5e6634bf7b4fa83a6dd3112607547001"},
|
||||
{file = "charset_normalizer-3.3.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:95f2a5796329323b8f0512e09dbb7a1860c46a39da62ecb2324f116fa8fdc85c"},
|
||||
{file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c002b4ffc0be611f0d9da932eb0f704fe2602a9a949d1f738e4c34c75b0863d5"},
|
||||
{file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a981a536974bbc7a512cf44ed14938cf01030a99e9b3a06dd59578882f06f985"},
|
||||
{file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3287761bc4ee9e33561a7e058c72ac0938c4f57fe49a09eae428fd88aafe7bb6"},
|
||||
{file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:42cb296636fcc8b0644486d15c12376cb9fa75443e00fb25de0b8602e64c1714"},
|
||||
{file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0a55554a2fa0d408816b3b5cedf0045f4b8e1a6065aec45849de2d6f3f8e9786"},
|
||||
{file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:c083af607d2515612056a31f0a8d9e0fcb5876b7bfc0abad3ecd275bc4ebc2d5"},
|
||||
{file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:87d1351268731db79e0f8e745d92493ee2841c974128ef629dc518b937d9194c"},
|
||||
{file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:bd8f7df7d12c2db9fab40bdd87a7c09b1530128315d047a086fa3ae3435cb3a8"},
|
||||
{file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:c180f51afb394e165eafe4ac2936a14bee3eb10debc9d9e4db8958fe36afe711"},
|
||||
{file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:8c622a5fe39a48f78944a87d4fb8a53ee07344641b0562c540d840748571b811"},
|
||||
{file = "charset_normalizer-3.3.2-cp37-cp37m-win32.whl", hash = "sha256:db364eca23f876da6f9e16c9da0df51aa4f104a972735574842618b8c6d999d4"},
|
||||
{file = "charset_normalizer-3.3.2-cp37-cp37m-win_amd64.whl", hash = "sha256:86216b5cee4b06df986d214f664305142d9c76df9b6512be2738aa72a2048f99"},
|
||||
{file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:6463effa3186ea09411d50efc7d85360b38d5f09b870c48e4600f63af490e56a"},
|
||||
{file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6c4caeef8fa63d06bd437cd4bdcf3ffefe6738fb1b25951440d80dc7df8c03ac"},
|
||||
{file = "charset_normalizer-3.3.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:37e55c8e51c236f95b033f6fb391d7d7970ba5fe7ff453dad675e88cf303377a"},
|
||||
{file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fb69256e180cb6c8a894fee62b3afebae785babc1ee98b81cdf68bbca1987f33"},
|
||||
{file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ae5f4161f18c61806f411a13b0310bea87f987c7d2ecdbdaad0e94eb2e404238"},
|
||||
{file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b2b0a0c0517616b6869869f8c581d4eb2dd83a4d79e0ebcb7d373ef9956aeb0a"},
|
||||
{file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:45485e01ff4d3630ec0d9617310448a8702f70e9c01906b0d0118bdf9d124cf2"},
|
||||
{file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eb00ed941194665c332bf8e078baf037d6c35d7c4f3102ea2d4f16ca94a26dc8"},
|
||||
{file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:2127566c664442652f024c837091890cb1942c30937add288223dc895793f898"},
|
||||
{file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a50aebfa173e157099939b17f18600f72f84eed3049e743b68ad15bd69b6bf99"},
|
||||
{file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:4d0d1650369165a14e14e1e47b372cfcb31d6ab44e6e33cb2d4e57265290044d"},
|
||||
{file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:923c0c831b7cfcb071580d3f46c4baf50f174be571576556269530f4bbd79d04"},
|
||||
{file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:06a81e93cd441c56a9b65d8e1d043daeb97a3d0856d177d5c90ba85acb3db087"},
|
||||
{file = "charset_normalizer-3.3.2-cp38-cp38-win32.whl", hash = "sha256:6ef1d82a3af9d3eecdba2321dc1b3c238245d890843e040e41e470ffa64c3e25"},
|
||||
{file = "charset_normalizer-3.3.2-cp38-cp38-win_amd64.whl", hash = "sha256:eb8821e09e916165e160797a6c17edda0679379a4be5c716c260e836e122f54b"},
|
||||
{file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:c235ebd9baae02f1b77bcea61bce332cb4331dc3617d254df3323aa01ab47bd4"},
|
||||
{file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5b4c145409bef602a690e7cfad0a15a55c13320ff7a3ad7ca59c13bb8ba4d45d"},
|
||||
{file = "charset_normalizer-3.3.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:68d1f8a9e9e37c1223b656399be5d6b448dea850bed7d0f87a8311f1ff3dabb0"},
|
||||
{file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22afcb9f253dac0696b5a4be4a1c0f8762f8239e21b99680099abd9b2b1b2269"},
|
||||
{file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e27ad930a842b4c5eb8ac0016b0a54f5aebbe679340c26101df33424142c143c"},
|
||||
{file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1f79682fbe303db92bc2b1136016a38a42e835d932bab5b3b1bfcfbf0640e519"},
|
||||
{file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b261ccdec7821281dade748d088bb6e9b69e6d15b30652b74cbbac25e280b796"},
|
||||
{file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:122c7fa62b130ed55f8f285bfd56d5f4b4a5b503609d181f9ad85e55c89f4185"},
|
||||
{file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:d0eccceffcb53201b5bfebb52600a5fb483a20b61da9dbc885f8b103cbe7598c"},
|
||||
{file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9f96df6923e21816da7e0ad3fd47dd8f94b2a5ce594e00677c0013018b813458"},
|
||||
{file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:7f04c839ed0b6b98b1a7501a002144b76c18fb1c1850c8b98d458ac269e26ed2"},
|
||||
{file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:34d1c8da1e78d2e001f363791c98a272bb734000fcef47a491c1e3b0505657a8"},
|
||||
{file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ff8fa367d09b717b2a17a052544193ad76cd49979c805768879cb63d9ca50561"},
|
||||
{file = "charset_normalizer-3.3.2-cp39-cp39-win32.whl", hash = "sha256:aed38f6e4fb3f5d6bf81bfa990a07806be9d83cf7bacef998ab1a9bd660a581f"},
|
||||
{file = "charset_normalizer-3.3.2-cp39-cp39-win_amd64.whl", hash = "sha256:b01b88d45a6fcb69667cd6d2f7a9aeb4bf53760d7fc536bf679ec94fe9f3ff3d"},
|
||||
{file = "charset_normalizer-3.3.2-py3-none-any.whl", hash = "sha256:3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "colorama"
|
||||
version = "0.4.6"
|
||||
description = "Cross-platform colored terminal text."
|
||||
optional = false
|
||||
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7"
|
||||
files = [
|
||||
{file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"},
|
||||
{file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cssselect"
|
||||
version = "1.2.0"
|
||||
description = "cssselect parses CSS3 Selectors and translates them to XPath 1.0"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
{file = "cssselect-1.2.0-py2.py3-none-any.whl", hash = "sha256:da1885f0c10b60c03ed5eccbb6b68d6eff248d91976fcde348f395d54c9fd35e"},
|
||||
{file = "cssselect-1.2.0.tar.gz", hash = "sha256:666b19839cfaddb9ce9d36bfe4c969132c647b92fc9088c4e23f786b30f1b3dc"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "exceptiongroup"
|
||||
version = "1.2.2"
|
||||
description = "Backport of PEP 654 (exception groups)"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
{file = "exceptiongroup-1.2.2-py3-none-any.whl", hash = "sha256:3111b9d131c238bec2f8f516e123e14ba243563fb135d3fe885990585aa7795b"},
|
||||
{file = "exceptiongroup-1.2.2.tar.gz", hash = "sha256:47c2edf7c6738fafb49fd34290706d1a1a2f4d1c6df275526b62cbb4aa5393cc"},
|
||||
]
|
||||
|
||||
[package.extras]
|
||||
test = ["pytest (>=6)"]
|
||||
|
||||
[[package]]
|
||||
name = "idna"
|
||||
version = "3.7"
|
||||
description = "Internationalized Domain Names in Applications (IDNA)"
|
||||
optional = false
|
||||
python-versions = ">=3.5"
|
||||
files = [
|
||||
{file = "idna-3.7-py3-none-any.whl", hash = "sha256:82fee1fc78add43492d3a1898bfa6d8a904cc97d8427f683ed8e798d07761aa0"},
|
||||
{file = "idna-3.7.tar.gz", hash = "sha256:028ff3aadf0609c1fd278d8ea3089299412a7a8b9bd005dd08b9f8285bcb5cfc"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "iniconfig"
|
||||
version = "2.0.0"
|
||||
description = "brain-dead simple config-ini parsing"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
{file = "iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"},
|
||||
{file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "jmespath"
|
||||
version = "1.0.1"
|
||||
description = "JSON Matching Expressions"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
{file = "jmespath-1.0.1-py3-none-any.whl", hash = "sha256:02e2e4cc71b5bcab88332eebf907519190dd9e6e82107fa7f83b1003a6252980"},
|
||||
{file = "jmespath-1.0.1.tar.gz", hash = "sha256:90261b206d6defd58fdd5e85f478bf633a2901798906be2ad389150c5c60edbe"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lxml"
|
||||
version = "5.2.2"
|
||||
description = "Powerful and Pythonic XML processing library combining libxml2/libxslt with the ElementTree API."
|
||||
optional = false
|
||||
python-versions = ">=3.6"
|
||||
files = [
|
||||
{file = "lxml-5.2.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:364d03207f3e603922d0d3932ef363d55bbf48e3647395765f9bfcbdf6d23632"},
|
||||
{file = "lxml-5.2.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:50127c186f191b8917ea2fb8b206fbebe87fd414a6084d15568c27d0a21d60db"},
|
||||
{file = "lxml-5.2.2-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:74e4f025ef3db1c6da4460dd27c118d8cd136d0391da4e387a15e48e5c975147"},
|
||||
{file = "lxml-5.2.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:981a06a3076997adf7c743dcd0d7a0415582661e2517c7d961493572e909aa1d"},
|
||||
{file = "lxml-5.2.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:aef5474d913d3b05e613906ba4090433c515e13ea49c837aca18bde190853dff"},
|
||||
{file = "lxml-5.2.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1e275ea572389e41e8b039ac076a46cb87ee6b8542df3fff26f5baab43713bca"},
|
||||
{file = "lxml-5.2.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f5b65529bb2f21ac7861a0e94fdbf5dc0daab41497d18223b46ee8515e5ad297"},
|
||||
{file = "lxml-5.2.2-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:bcc98f911f10278d1daf14b87d65325851a1d29153caaf146877ec37031d5f36"},
|
||||
{file = "lxml-5.2.2-cp310-cp310-manylinux_2_28_ppc64le.whl", hash = "sha256:b47633251727c8fe279f34025844b3b3a3e40cd1b198356d003aa146258d13a2"},
|
||||
{file = "lxml-5.2.2-cp310-cp310-manylinux_2_28_s390x.whl", hash = "sha256:fbc9d316552f9ef7bba39f4edfad4a734d3d6f93341232a9dddadec4f15d425f"},
|
||||
{file = "lxml-5.2.2-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:13e69be35391ce72712184f69000cda04fc89689429179bc4c0ae5f0b7a8c21b"},
|
||||
{file = "lxml-5.2.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:3b6a30a9ab040b3f545b697cb3adbf3696c05a3a68aad172e3fd7ca73ab3c835"},
|
||||
{file = "lxml-5.2.2-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:a233bb68625a85126ac9f1fc66d24337d6e8a0f9207b688eec2e7c880f012ec0"},
|
||||
{file = "lxml-5.2.2-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:dfa7c241073d8f2b8e8dbc7803c434f57dbb83ae2a3d7892dd068d99e96efe2c"},
|
||||
{file = "lxml-5.2.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:1a7aca7964ac4bb07680d5c9d63b9d7028cace3e2d43175cb50bba8c5ad33316"},
|
||||
{file = "lxml-5.2.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:ae4073a60ab98529ab8a72ebf429f2a8cc612619a8c04e08bed27450d52103c0"},
|
||||
{file = "lxml-5.2.2-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:ffb2be176fed4457e445fe540617f0252a72a8bc56208fd65a690fdb1f57660b"},
|
||||
{file = "lxml-5.2.2-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:e290d79a4107d7d794634ce3e985b9ae4f920380a813717adf61804904dc4393"},
|
||||
{file = "lxml-5.2.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:96e85aa09274955bb6bd483eaf5b12abadade01010478154b0ec70284c1b1526"},
|
||||
{file = "lxml-5.2.2-cp310-cp310-win32.whl", hash = "sha256:f956196ef61369f1685d14dad80611488d8dc1ef00be57c0c5a03064005b0f30"},
|
||||
{file = "lxml-5.2.2-cp310-cp310-win_amd64.whl", hash = "sha256:875a3f90d7eb5c5d77e529080d95140eacb3c6d13ad5b616ee8095447b1d22e7"},
|
||||
{file = "lxml-5.2.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:45f9494613160d0405682f9eee781c7e6d1bf45f819654eb249f8f46a2c22545"},
|
||||
{file = "lxml-5.2.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b0b3f2df149efb242cee2ffdeb6674b7f30d23c9a7af26595099afaf46ef4e88"},
|
||||
{file = "lxml-5.2.2-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d28cb356f119a437cc58a13f8135ab8a4c8ece18159eb9194b0d269ec4e28083"},
|
||||
{file = "lxml-5.2.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:657a972f46bbefdbba2d4f14413c0d079f9ae243bd68193cb5061b9732fa54c1"},
|
||||
{file = "lxml-5.2.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b74b9ea10063efb77a965a8d5f4182806fbf59ed068b3c3fd6f30d2ac7bee734"},
|
||||
{file = "lxml-5.2.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:07542787f86112d46d07d4f3c4e7c760282011b354d012dc4141cc12a68cef5f"},
|
||||
{file = "lxml-5.2.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:303f540ad2dddd35b92415b74b900c749ec2010e703ab3bfd6660979d01fd4ed"},
|
||||
{file = "lxml-5.2.2-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:2eb2227ce1ff998faf0cd7fe85bbf086aa41dfc5af3b1d80867ecfe75fb68df3"},
|
||||
{file = "lxml-5.2.2-cp311-cp311-manylinux_2_28_ppc64le.whl", hash = "sha256:1d8a701774dfc42a2f0b8ccdfe7dbc140500d1049e0632a611985d943fcf12df"},
|
||||
{file = "lxml-5.2.2-cp311-cp311-manylinux_2_28_s390x.whl", hash = "sha256:56793b7a1a091a7c286b5f4aa1fe4ae5d1446fe742d00cdf2ffb1077865db10d"},
|
||||
{file = "lxml-5.2.2-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:eb00b549b13bd6d884c863554566095bf6fa9c3cecb2e7b399c4bc7904cb33b5"},
|
||||
{file = "lxml-5.2.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:1a2569a1f15ae6c8c64108a2cd2b4a858fc1e13d25846be0666fc144715e32ab"},
|
||||
{file = "lxml-5.2.2-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:8cf85a6e40ff1f37fe0f25719aadf443686b1ac7652593dc53c7ef9b8492b115"},
|
||||
{file = "lxml-5.2.2-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:d237ba6664b8e60fd90b8549a149a74fcc675272e0e95539a00522e4ca688b04"},
|
||||
{file = "lxml-5.2.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:0b3f5016e00ae7630a4b83d0868fca1e3d494c78a75b1c7252606a3a1c5fc2ad"},
|
||||
{file = "lxml-5.2.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:23441e2b5339bc54dc949e9e675fa35efe858108404ef9aa92f0456929ef6fe8"},
|
||||
{file = "lxml-5.2.2-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:2fb0ba3e8566548d6c8e7dd82a8229ff47bd8fb8c2da237607ac8e5a1b8312e5"},
|
||||
{file = "lxml-5.2.2-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:79d1fb9252e7e2cfe4de6e9a6610c7cbb99b9708e2c3e29057f487de5a9eaefa"},
|
||||
{file = "lxml-5.2.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:6dcc3d17eac1df7859ae01202e9bb11ffa8c98949dcbeb1069c8b9a75917e01b"},
|
||||
{file = "lxml-5.2.2-cp311-cp311-win32.whl", hash = "sha256:4c30a2f83677876465f44c018830f608fa3c6a8a466eb223535035fbc16f3438"},
|
||||
{file = "lxml-5.2.2-cp311-cp311-win_amd64.whl", hash = "sha256:49095a38eb333aaf44c06052fd2ec3b8f23e19747ca7ec6f6c954ffea6dbf7be"},
|
||||
{file = "lxml-5.2.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:7429e7faa1a60cad26ae4227f4dd0459efde239e494c7312624ce228e04f6391"},
|
||||
{file = "lxml-5.2.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:50ccb5d355961c0f12f6cf24b7187dbabd5433f29e15147a67995474f27d1776"},
|
||||
{file = "lxml-5.2.2-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dc911208b18842a3a57266d8e51fc3cfaccee90a5351b92079beed912a7914c2"},
|
||||
{file = "lxml-5.2.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:33ce9e786753743159799fdf8e92a5da351158c4bfb6f2db0bf31e7892a1feb5"},
|
||||
{file = "lxml-5.2.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ec87c44f619380878bd49ca109669c9f221d9ae6883a5bcb3616785fa8f94c97"},
|
||||
{file = "lxml-5.2.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:08ea0f606808354eb8f2dfaac095963cb25d9d28e27edcc375d7b30ab01abbf6"},
|
||||
{file = "lxml-5.2.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75a9632f1d4f698b2e6e2e1ada40e71f369b15d69baddb8968dcc8e683839b18"},
|
||||
{file = "lxml-5.2.2-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:74da9f97daec6928567b48c90ea2c82a106b2d500f397eeb8941e47d30b1ca85"},
|
||||
{file = "lxml-5.2.2-cp312-cp312-manylinux_2_28_ppc64le.whl", hash = "sha256:0969e92af09c5687d769731e3f39ed62427cc72176cebb54b7a9d52cc4fa3b73"},
|
||||
{file = "lxml-5.2.2-cp312-cp312-manylinux_2_28_s390x.whl", hash = "sha256:9164361769b6ca7769079f4d426a41df6164879f7f3568be9086e15baca61466"},
|
||||
{file = "lxml-5.2.2-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:d26a618ae1766279f2660aca0081b2220aca6bd1aa06b2cf73f07383faf48927"},
|
||||
{file = "lxml-5.2.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:ab67ed772c584b7ef2379797bf14b82df9aa5f7438c5b9a09624dd834c1c1aaf"},
|
||||
{file = "lxml-5.2.2-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:3d1e35572a56941b32c239774d7e9ad724074d37f90c7a7d499ab98761bd80cf"},
|
||||
{file = "lxml-5.2.2-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:8268cbcd48c5375f46e000adb1390572c98879eb4f77910c6053d25cc3ac2c67"},
|
||||
{file = "lxml-5.2.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:e282aedd63c639c07c3857097fc0e236f984ceb4089a8b284da1c526491e3f3d"},
|
||||
{file = "lxml-5.2.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6dfdc2bfe69e9adf0df4915949c22a25b39d175d599bf98e7ddf620a13678585"},
|
||||
{file = "lxml-5.2.2-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:4aefd911793b5d2d7a921233a54c90329bf3d4a6817dc465f12ffdfe4fc7b8fe"},
|
||||
{file = "lxml-5.2.2-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:8b8df03a9e995b6211dafa63b32f9d405881518ff1ddd775db4e7b98fb545e1c"},
|
||||
{file = "lxml-5.2.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:f11ae142f3a322d44513de1018b50f474f8f736bc3cd91d969f464b5bfef8836"},
|
||||
{file = "lxml-5.2.2-cp312-cp312-win32.whl", hash = "sha256:16a8326e51fcdffc886294c1e70b11ddccec836516a343f9ed0f82aac043c24a"},
|
||||
{file = "lxml-5.2.2-cp312-cp312-win_amd64.whl", hash = "sha256:bbc4b80af581e18568ff07f6395c02114d05f4865c2812a1f02f2eaecf0bfd48"},
|
||||
{file = "lxml-5.2.2-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:e3d9d13603410b72787579769469af730c38f2f25505573a5888a94b62b920f8"},
|
||||
{file = "lxml-5.2.2-cp36-cp36m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:38b67afb0a06b8575948641c1d6d68e41b83a3abeae2ca9eed2ac59892b36706"},
|
||||
{file = "lxml-5.2.2-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c689d0d5381f56de7bd6966a4541bff6e08bf8d3871bbd89a0c6ab18aa699573"},
|
||||
{file = "lxml-5.2.2-cp36-cp36m-manylinux_2_28_x86_64.whl", hash = "sha256:cf2a978c795b54c539f47964ec05e35c05bd045db5ca1e8366988c7f2fe6b3ce"},
|
||||
{file = "lxml-5.2.2-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:739e36ef7412b2bd940f75b278749106e6d025e40027c0b94a17ef7968d55d56"},
|
||||
{file = "lxml-5.2.2-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:d8bbcd21769594dbba9c37d3c819e2d5847656ca99c747ddb31ac1701d0c0ed9"},
|
||||
{file = "lxml-5.2.2-cp36-cp36m-musllinux_1_2_x86_64.whl", hash = "sha256:2304d3c93f2258ccf2cf7a6ba8c761d76ef84948d87bf9664e14d203da2cd264"},
|
||||
{file = "lxml-5.2.2-cp36-cp36m-win32.whl", hash = "sha256:02437fb7308386867c8b7b0e5bc4cd4b04548b1c5d089ffb8e7b31009b961dc3"},
|
||||
{file = "lxml-5.2.2-cp36-cp36m-win_amd64.whl", hash = "sha256:edcfa83e03370032a489430215c1e7783128808fd3e2e0a3225deee278585196"},
|
||||
{file = "lxml-5.2.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:28bf95177400066596cdbcfc933312493799382879da504633d16cf60bba735b"},
|
||||
{file = "lxml-5.2.2-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3a745cc98d504d5bd2c19b10c79c61c7c3df9222629f1b6210c0368177589fb8"},
|
||||
{file = "lxml-5.2.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1b590b39ef90c6b22ec0be925b211298e810b4856909c8ca60d27ffbca6c12e6"},
|
||||
{file = "lxml-5.2.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b336b0416828022bfd5a2e3083e7f5ba54b96242159f83c7e3eebaec752f1716"},
|
||||
{file = "lxml-5.2.2-cp37-cp37m-manylinux_2_28_aarch64.whl", hash = "sha256:c2faf60c583af0d135e853c86ac2735ce178f0e338a3c7f9ae8f622fd2eb788c"},
|
||||
{file = "lxml-5.2.2-cp37-cp37m-manylinux_2_28_x86_64.whl", hash = "sha256:4bc6cb140a7a0ad1f7bc37e018d0ed690b7b6520ade518285dc3171f7a117905"},
|
||||
{file = "lxml-5.2.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:7ff762670cada8e05b32bf1e4dc50b140790909caa8303cfddc4d702b71ea184"},
|
||||
{file = "lxml-5.2.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:57f0a0bbc9868e10ebe874e9f129d2917750adf008fe7b9c1598c0fbbfdde6a6"},
|
||||
{file = "lxml-5.2.2-cp37-cp37m-musllinux_1_2_aarch64.whl", hash = "sha256:a6d2092797b388342c1bc932077ad232f914351932353e2e8706851c870bca1f"},
|
||||
{file = "lxml-5.2.2-cp37-cp37m-musllinux_1_2_x86_64.whl", hash = "sha256:60499fe961b21264e17a471ec296dcbf4365fbea611bf9e303ab69db7159ce61"},
|
||||
{file = "lxml-5.2.2-cp37-cp37m-win32.whl", hash = "sha256:d9b342c76003c6b9336a80efcc766748a333573abf9350f4094ee46b006ec18f"},
|
||||
{file = "lxml-5.2.2-cp37-cp37m-win_amd64.whl", hash = "sha256:b16db2770517b8799c79aa80f4053cd6f8b716f21f8aca962725a9565ce3ee40"},
|
||||
{file = "lxml-5.2.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:7ed07b3062b055d7a7f9d6557a251cc655eed0b3152b76de619516621c56f5d3"},
|
||||
{file = "lxml-5.2.2-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f60fdd125d85bf9c279ffb8e94c78c51b3b6a37711464e1f5f31078b45002421"},
|
||||
{file = "lxml-5.2.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8a7e24cb69ee5f32e003f50e016d5fde438010c1022c96738b04fc2423e61706"},
|
||||
{file = "lxml-5.2.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:23cfafd56887eaed93d07bc4547abd5e09d837a002b791e9767765492a75883f"},
|
||||
{file = "lxml-5.2.2-cp38-cp38-manylinux_2_28_aarch64.whl", hash = "sha256:19b4e485cd07b7d83e3fe3b72132e7df70bfac22b14fe4bf7a23822c3a35bff5"},
|
||||
{file = "lxml-5.2.2-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:7ce7ad8abebe737ad6143d9d3bf94b88b93365ea30a5b81f6877ec9c0dee0a48"},
|
||||
{file = "lxml-5.2.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:e49b052b768bb74f58c7dda4e0bdf7b79d43a9204ca584ffe1fb48a6f3c84c66"},
|
||||
{file = "lxml-5.2.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:d14a0d029a4e176795cef99c056d58067c06195e0c7e2dbb293bf95c08f772a3"},
|
||||
{file = "lxml-5.2.2-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:be49ad33819d7dcc28a309b86d4ed98e1a65f3075c6acd3cd4fe32103235222b"},
|
||||
{file = "lxml-5.2.2-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:a6d17e0370d2516d5bb9062c7b4cb731cff921fc875644c3d751ad857ba9c5b1"},
|
||||
{file = "lxml-5.2.2-cp38-cp38-win32.whl", hash = "sha256:5b8c041b6265e08eac8a724b74b655404070b636a8dd6d7a13c3adc07882ef30"},
|
||||
{file = "lxml-5.2.2-cp38-cp38-win_amd64.whl", hash = "sha256:f61efaf4bed1cc0860e567d2ecb2363974d414f7f1f124b1df368bbf183453a6"},
|
||||
{file = "lxml-5.2.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:fb91819461b1b56d06fa4bcf86617fac795f6a99d12239fb0c68dbeba41a0a30"},
|
||||
{file = "lxml-5.2.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:d4ed0c7cbecde7194cd3228c044e86bf73e30a23505af852857c09c24e77ec5d"},
|
||||
{file = "lxml-5.2.2-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:54401c77a63cc7d6dc4b4e173bb484f28a5607f3df71484709fe037c92d4f0ed"},
|
||||
{file = "lxml-5.2.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:625e3ef310e7fa3a761d48ca7ea1f9d8718a32b1542e727d584d82f4453d5eeb"},
|
||||
{file = "lxml-5.2.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:519895c99c815a1a24a926d5b60627ce5ea48e9f639a5cd328bda0515ea0f10c"},
|
||||
{file = "lxml-5.2.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c7079d5eb1c1315a858bbf180000757db8ad904a89476653232db835c3114001"},
|
||||
{file = "lxml-5.2.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:343ab62e9ca78094f2306aefed67dcfad61c4683f87eee48ff2fd74902447726"},
|
||||
{file = "lxml-5.2.2-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:cd9e78285da6c9ba2d5c769628f43ef66d96ac3085e59b10ad4f3707980710d3"},
|
||||
{file = "lxml-5.2.2-cp39-cp39-manylinux_2_28_ppc64le.whl", hash = "sha256:546cf886f6242dff9ec206331209db9c8e1643ae642dea5fdbecae2453cb50fd"},
|
||||
{file = "lxml-5.2.2-cp39-cp39-manylinux_2_28_s390x.whl", hash = "sha256:02f6a8eb6512fdc2fd4ca10a49c341c4e109aa6e9448cc4859af5b949622715a"},
|
||||
{file = "lxml-5.2.2-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:339ee4a4704bc724757cd5dd9dc8cf4d00980f5d3e6e06d5847c1b594ace68ab"},
|
||||
{file = "lxml-5.2.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0a028b61a2e357ace98b1615fc03f76eb517cc028993964fe08ad514b1e8892d"},
|
||||
{file = "lxml-5.2.2-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:f90e552ecbad426eab352e7b2933091f2be77115bb16f09f78404861c8322981"},
|
||||
{file = "lxml-5.2.2-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:d83e2d94b69bf31ead2fa45f0acdef0757fa0458a129734f59f67f3d2eb7ef32"},
|
||||
{file = "lxml-5.2.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:a02d3c48f9bb1e10c7788d92c0c7db6f2002d024ab6e74d6f45ae33e3d0288a3"},
|
||||
{file = "lxml-5.2.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:6d68ce8e7b2075390e8ac1e1d3a99e8b6372c694bbe612632606d1d546794207"},
|
||||
{file = "lxml-5.2.2-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:453d037e09a5176d92ec0fd282e934ed26d806331a8b70ab431a81e2fbabf56d"},
|
||||
{file = "lxml-5.2.2-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:3b019d4ee84b683342af793b56bb35034bd749e4cbdd3d33f7d1107790f8c472"},
|
||||
{file = "lxml-5.2.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:cb3942960f0beb9f46e2a71a3aca220d1ca32feb5a398656be934320804c0df9"},
|
||||
{file = "lxml-5.2.2-cp39-cp39-win32.whl", hash = "sha256:ac6540c9fff6e3813d29d0403ee7a81897f1d8ecc09a8ff84d2eea70ede1cdbf"},
|
||||
{file = "lxml-5.2.2-cp39-cp39-win_amd64.whl", hash = "sha256:610b5c77428a50269f38a534057444c249976433f40f53e3b47e68349cca1425"},
|
||||
{file = "lxml-5.2.2-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:b537bd04d7ccd7c6350cdaaaad911f6312cbd61e6e6045542f781c7f8b2e99d2"},
|
||||
{file = "lxml-5.2.2-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4820c02195d6dfb7b8508ff276752f6b2ff8b64ae5d13ebe02e7667e035000b9"},
|
||||
{file = "lxml-5.2.2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f2a09f6184f17a80897172863a655467da2b11151ec98ba8d7af89f17bf63dae"},
|
||||
{file = "lxml-5.2.2-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:76acba4c66c47d27c8365e7c10b3d8016a7da83d3191d053a58382311a8bf4e1"},
|
||||
{file = "lxml-5.2.2-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:b128092c927eaf485928cec0c28f6b8bead277e28acf56800e972aa2c2abd7a2"},
|
||||
{file = "lxml-5.2.2-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:ae791f6bd43305aade8c0e22f816b34f3b72b6c820477aab4d18473a37e8090b"},
|
||||
{file = "lxml-5.2.2-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:a2f6a1bc2460e643785a2cde17293bd7a8f990884b822f7bca47bee0a82fc66b"},
|
||||
{file = "lxml-5.2.2-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8e8d351ff44c1638cb6e980623d517abd9f580d2e53bfcd18d8941c052a5a009"},
|
||||
{file = "lxml-5.2.2-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bec4bd9133420c5c52d562469c754f27c5c9e36ee06abc169612c959bd7dbb07"},
|
||||
{file = "lxml-5.2.2-pp37-pypy37_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:55ce6b6d803890bd3cc89975fca9de1dff39729b43b73cb15ddd933b8bc20484"},
|
||||
{file = "lxml-5.2.2-pp37-pypy37_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:8ab6a358d1286498d80fe67bd3d69fcbc7d1359b45b41e74c4a26964ca99c3f8"},
|
||||
{file = "lxml-5.2.2-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:06668e39e1f3c065349c51ac27ae430719d7806c026fec462e5693b08b95696b"},
|
||||
{file = "lxml-5.2.2-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:9cd5323344d8ebb9fb5e96da5de5ad4ebab993bbf51674259dbe9d7a18049525"},
|
||||
{file = "lxml-5.2.2-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:89feb82ca055af0fe797a2323ec9043b26bc371365847dbe83c7fd2e2f181c34"},
|
||||
{file = "lxml-5.2.2-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e481bba1e11ba585fb06db666bfc23dbe181dbafc7b25776156120bf12e0d5a6"},
|
||||
{file = "lxml-5.2.2-pp38-pypy38_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:9d6c6ea6a11ca0ff9cd0390b885984ed31157c168565702959c25e2191674a14"},
|
||||
{file = "lxml-5.2.2-pp38-pypy38_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:3d98de734abee23e61f6b8c2e08a88453ada7d6486dc7cdc82922a03968928db"},
|
||||
{file = "lxml-5.2.2-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:69ab77a1373f1e7563e0fb5a29a8440367dec051da6c7405333699d07444f511"},
|
||||
{file = "lxml-5.2.2-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:34e17913c431f5ae01d8658dbf792fdc457073dcdfbb31dc0cc6ab256e664a8d"},
|
||||
{file = "lxml-5.2.2-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:05f8757b03208c3f50097761be2dea0aba02e94f0dc7023ed73a7bb14ff11eb0"},
|
||||
{file = "lxml-5.2.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6a520b4f9974b0a0a6ed73c2154de57cdfd0c8800f4f15ab2b73238ffed0b36e"},
|
||||
{file = "lxml-5.2.2-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:5e097646944b66207023bc3c634827de858aebc226d5d4d6d16f0b77566ea182"},
|
||||
{file = "lxml-5.2.2-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:b5e4ef22ff25bfd4ede5f8fb30f7b24446345f3e79d9b7455aef2836437bc38a"},
|
||||
{file = "lxml-5.2.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:ff69a9a0b4b17d78170c73abe2ab12084bdf1691550c5629ad1fe7849433f324"},
|
||||
{file = "lxml-5.2.2.tar.gz", hash = "sha256:bb2dc4898180bea79863d5487e5f9c7c34297414bad54bcd0f0852aee9cfdb87"},
|
||||
]
|
||||
|
||||
[package.extras]
|
||||
cssselect = ["cssselect (>=0.7)"]
|
||||
html-clean = ["lxml-html-clean"]
|
||||
html5 = ["html5lib"]
|
||||
htmlsoup = ["BeautifulSoup4"]
|
||||
source = ["Cython (>=3.0.10)"]
|
||||
|
||||
[[package]]
|
||||
name = "packaging"
|
||||
version = "24.1"
|
||||
description = "Core utilities for Python packages"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "packaging-24.1-py3-none-any.whl", hash = "sha256:5b8f2217dbdbd2f7f384c41c628544e6d52f2d0f53c6d0c3ea61aa5d1d7ff124"},
|
||||
{file = "packaging-24.1.tar.gz", hash = "sha256:026ed72c8ed3fcce5bf8950572258698927fd1dbda10a5e981cdf0ac37f4f002"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "parsel"
|
||||
version = "1.9.1"
|
||||
description = "Parsel is a library to extract data from HTML and XML using XPath and CSS selectors"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "parsel-1.9.1-py2.py3-none-any.whl", hash = "sha256:c4a777ee6c3ff5e39652b58e351c5cf02c12ff420d05b07a7966aebb68ab1700"},
|
||||
{file = "parsel-1.9.1.tar.gz", hash = "sha256:14e00dc07731c9030db620c195fcae884b5b4848e9f9c523c6119f708ccfa9ac"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
cssselect = ">=1.2.0"
|
||||
jmespath = "*"
|
||||
lxml = "*"
|
||||
packaging = "*"
|
||||
w3lib = ">=1.19.0"
|
||||
|
||||
[[package]]
|
||||
name = "pluggy"
|
||||
version = "1.5.0"
|
||||
description = "plugin and hook calling mechanisms for python"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669"},
|
||||
{file = "pluggy-1.5.0.tar.gz", hash = "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1"},
|
||||
]
|
||||
|
||||
[package.extras]
|
||||
dev = ["pre-commit", "tox"]
|
||||
testing = ["pytest", "pytest-benchmark"]
|
||||
|
||||
[[package]]
|
||||
name = "pytest"
|
||||
version = "8.3.2"
|
||||
description = "pytest: simple powerful testing with Python"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "pytest-8.3.2-py3-none-any.whl", hash = "sha256:4ba08f9ae7dcf84ded419494d229b48d0903ea6407b030eaec46df5e6a73bba5"},
|
||||
{file = "pytest-8.3.2.tar.gz", hash = "sha256:c132345d12ce551242c87269de812483f5bcc87cdbb4722e48487ba194f9fdce"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
colorama = {version = "*", markers = "sys_platform == \"win32\""}
|
||||
exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""}
|
||||
iniconfig = "*"
|
||||
packaging = "*"
|
||||
pluggy = ">=1.5,<2"
|
||||
tomli = {version = ">=1", markers = "python_version < \"3.11\""}
|
||||
|
||||
[package.extras]
|
||||
dev = ["argcomplete", "attrs (>=19.2)", "hypothesis (>=3.56)", "mock", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"]
|
||||
|
||||
[[package]]
|
||||
name = "requests"
|
||||
version = "2.32.3"
|
||||
description = "Python HTTP for Humans."
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6"},
|
||||
{file = "requests-2.32.3.tar.gz", hash = "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
certifi = ">=2017.4.17"
|
||||
charset-normalizer = ">=2,<4"
|
||||
idna = ">=2.5,<4"
|
||||
urllib3 = ">=1.21.1,<3"
|
||||
|
||||
[package.extras]
|
||||
socks = ["PySocks (>=1.5.6,!=1.5.7)"]
|
||||
use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"]
|
||||
|
||||
[[package]]
|
||||
name = "tomli"
|
||||
version = "2.0.1"
|
||||
description = "A lil' TOML parser"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
{file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"},
|
||||
{file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "urllib3"
|
||||
version = "2.2.2"
|
||||
description = "HTTP library with thread-safe connection pooling, file post, and more."
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "urllib3-2.2.2-py3-none-any.whl", hash = "sha256:a448b2f64d686155468037e1ace9f2d2199776e17f0a46610480d311f73e3472"},
|
||||
{file = "urllib3-2.2.2.tar.gz", hash = "sha256:dd505485549a7a552833da5e6063639d0d177c04f23bc3864e41e5dc5f612168"},
|
||||
]
|
||||
|
||||
[package.extras]
|
||||
brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"]
|
||||
h2 = ["h2 (>=4,<5)"]
|
||||
socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"]
|
||||
zstd = ["zstandard (>=0.18.0)"]
|
||||
|
||||
[[package]]
|
||||
name = "w3lib"
|
||||
version = "2.2.1"
|
||||
description = "Library of web-related functions"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "w3lib-2.2.1-py3-none-any.whl", hash = "sha256:e56d81c6a6bf507d7039e0c95745ab80abd24b465eb0f248af81e3eaa46eb510"},
|
||||
{file = "w3lib-2.2.1.tar.gz", hash = "sha256:756ff2d94c64e41c8d7c0c59fea12a5d0bc55e33a531c7988b4a163deb9b07dd"},
|
||||
]
|
||||
|
||||
[metadata]
|
||||
lock-version = "2.0"
|
||||
python-versions = "^3.10"
|
||||
content-hash = "67a578afce6d570192e284e76d3745083c4793ad80dffe69a414addd9fedcdce"
|
26
pyproject.toml
Normal file
26
pyproject.toml
Normal file
@ -0,0 +1,26 @@
|
||||
[tool.poetry]
|
||||
name = "humblebundle-downloader"
|
||||
version = "0.4.1"
|
||||
description = "Download your Humble Bundle library"
|
||||
authors = ["Eddy Hintze <eddy@gitx.codes>"]
|
||||
license = "MIT"
|
||||
readme = "README.md"
|
||||
|
||||
[tool.poetry.urls]
|
||||
homepage = "https://github.com/xtream1101/humblebundle-downloader"
|
||||
repository = "https://github.com/xtream1101/humblebundle-downloader"
|
||||
|
||||
[tool.poetry.scripts]
|
||||
hbd = "humblebundle_downloader.cli:cli"
|
||||
|
||||
[tool.poetry.dependencies]
|
||||
python = "^3.10"
|
||||
requests = "^2.32.3"
|
||||
parsel = "^1.9.1"
|
||||
|
||||
[tool.poetry.group.test.dependencies]
|
||||
pytest = "^8.3.2"
|
||||
|
||||
[build-system]
|
||||
requires = ["poetry-core"]
|
||||
build-backend = "poetry.core.masonry.api"
|
34
setup.py
34
setup.py
@ -1,34 +0,0 @@
|
||||
from setuptools import setup
|
||||
from humblebundle_downloader._version import __version__
|
||||
|
||||
|
||||
with open('README.md', 'r') as f:
|
||||
long_description = f.read()
|
||||
|
||||
setup(
|
||||
name='humblebundle-downloader',
|
||||
packages=['humblebundle_downloader'],
|
||||
version=__version__,
|
||||
description='Download your Humble Bundle library',
|
||||
long_description=long_description,
|
||||
long_description_content_type='text/markdown',
|
||||
author='Eddy Hintze',
|
||||
author_email="eddy@hintze.co",
|
||||
url="https://github.com/xtream1101/humblebundle-downloader",
|
||||
license='MIT',
|
||||
classifiers=[
|
||||
"Programming Language :: Python :: 3",
|
||||
"Operating System :: OS Independent",
|
||||
],
|
||||
entry_points={
|
||||
'console_scripts': [
|
||||
'hbd=humblebundle_downloader.cli:cli',
|
||||
],
|
||||
},
|
||||
python_requires='~=3.4',
|
||||
install_requires=[
|
||||
'requests',
|
||||
'parsel',
|
||||
],
|
||||
|
||||
)
|
@ -4,13 +4,13 @@ from humblebundle_downloader.cli import parse_args
|
||||
|
||||
def test_old_action_format():
|
||||
with pytest.raises(DeprecationWarning):
|
||||
_ = parse_args(['download', '-l', 'some_path', '-c', 'fake_cookie'])
|
||||
_ = parse_args(["download", "-l", "some_path", "-c", "fake_cookie"])
|
||||
|
||||
|
||||
def test_no_action():
|
||||
args = parse_args(['-l', 'some_path', '-c', 'fake_cookie'])
|
||||
assert args.library_path == 'some_path'
|
||||
assert args.cookie_file == 'fake_cookie'
|
||||
args = parse_args(["-l", "some_path", "-c", "fake_cookie"])
|
||||
assert args.library_path == "some_path"
|
||||
assert args.cookie_file == "fake_cookie"
|
||||
|
||||
|
||||
def test_no_args():
|
||||
|
@ -6,46 +6,46 @@ from humblebundle_downloader.download_library import DownloadLibrary
|
||||
###
|
||||
def test_include_logic_has_values():
|
||||
dl = DownloadLibrary(
|
||||
'fake_library_path',
|
||||
ext_include=['pdf', 'EPub'],
|
||||
"fake_library_path",
|
||||
ext_include=["pdf", "EPub"],
|
||||
)
|
||||
assert dl._should_download_file_type('pdf') is True
|
||||
assert dl._should_download_file_type('df') is False
|
||||
assert dl._should_download_file_type('ePub') is True
|
||||
assert dl._should_download_file_type('mobi') is False
|
||||
assert dl._should_download_file_type("pdf") is True
|
||||
assert dl._should_download_file_type("df") is False
|
||||
assert dl._should_download_file_type("ePub") is True
|
||||
assert dl._should_download_file_type("mobi") is False
|
||||
|
||||
|
||||
def test_include_logic_empty():
|
||||
dl = DownloadLibrary(
|
||||
'fake_library_path',
|
||||
"fake_library_path",
|
||||
ext_include=[],
|
||||
)
|
||||
assert dl._should_download_file_type('pdf') is True
|
||||
assert dl._should_download_file_type('df') is True
|
||||
assert dl._should_download_file_type('EPub') is True
|
||||
assert dl._should_download_file_type('mobi') is True
|
||||
assert dl._should_download_file_type("pdf") is True
|
||||
assert dl._should_download_file_type("df") is True
|
||||
assert dl._should_download_file_type("EPub") is True
|
||||
assert dl._should_download_file_type("mobi") is True
|
||||
|
||||
|
||||
def test_exclude_logic_has_values():
|
||||
dl = DownloadLibrary(
|
||||
'fake_library_path',
|
||||
ext_exclude=['pdf', 'EPub'],
|
||||
"fake_library_path",
|
||||
ext_exclude=["pdf", "EPub"],
|
||||
)
|
||||
assert dl._should_download_file_type('pdf') is False
|
||||
assert dl._should_download_file_type('df') is True
|
||||
assert dl._should_download_file_type('ePub') is False
|
||||
assert dl._should_download_file_type('mobi') is True
|
||||
assert dl._should_download_file_type("pdf") is False
|
||||
assert dl._should_download_file_type("df") is True
|
||||
assert dl._should_download_file_type("ePub") is False
|
||||
assert dl._should_download_file_type("mobi") is True
|
||||
|
||||
|
||||
def test_exclude_logic_empty():
|
||||
dl = DownloadLibrary(
|
||||
'fake_library_path',
|
||||
"fake_library_path",
|
||||
ext_exclude=[],
|
||||
)
|
||||
assert dl._should_download_file_type('pdf') is True
|
||||
assert dl._should_download_file_type('df') is True
|
||||
assert dl._should_download_file_type('EPub') is True
|
||||
assert dl._should_download_file_type('mobi') is True
|
||||
assert dl._should_download_file_type("pdf") is True
|
||||
assert dl._should_download_file_type("df") is True
|
||||
assert dl._should_download_file_type("EPub") is True
|
||||
assert dl._should_download_file_type("mobi") is True
|
||||
|
||||
|
||||
###
|
||||
@ -53,26 +53,26 @@ def test_exclude_logic_empty():
|
||||
###
|
||||
def test_download_platform_filter_none():
|
||||
dl = DownloadLibrary(
|
||||
'fake_library_path',
|
||||
"fake_library_path",
|
||||
platform_include=None,
|
||||
)
|
||||
assert dl._should_download_platform('ebook') is True
|
||||
assert dl._should_download_platform('audio') is True
|
||||
assert dl._should_download_platform("ebook") is True
|
||||
assert dl._should_download_platform("audio") is True
|
||||
|
||||
|
||||
def test_download_platform_filter_blank():
|
||||
dl = DownloadLibrary(
|
||||
'fake_library_path',
|
||||
"fake_library_path",
|
||||
platform_include=[],
|
||||
)
|
||||
assert dl._should_download_platform('ebook') is True
|
||||
assert dl._should_download_platform('audio') is True
|
||||
assert dl._should_download_platform("ebook") is True
|
||||
assert dl._should_download_platform("audio") is True
|
||||
|
||||
|
||||
def test_download_platform_filter_audio():
|
||||
dl = DownloadLibrary(
|
||||
'fake_library_path',
|
||||
platform_include=['audio'],
|
||||
"fake_library_path",
|
||||
platform_include=["audio"],
|
||||
)
|
||||
assert dl._should_download_platform('ebook') is False
|
||||
assert dl._should_download_platform('audio') is True
|
||||
assert dl._should_download_platform("ebook") is False
|
||||
assert dl._should_download_platform("audio") is True
|
||||
|
Loading…
Reference in New Issue
Block a user