nber-cli 0.1.2__tar.gz → 0.1.4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {nber_cli-0.1.2 → nber_cli-0.1.4}/.gitignore +5 -0
- nber_cli-0.1.4/CHANGELOG.md +37 -0
- {nber_cli-0.1.2 → nber_cli-0.1.4}/PKG-INFO +30 -4
- nber_cli-0.1.4/README.md +64 -0
- {nber_cli-0.1.2 → nber_cli-0.1.4}/pyproject.toml +4 -2
- nber_cli-0.1.4/src/nber_cli/__init__.py +67 -0
- nber_cli-0.1.4/src/nber_cli/__main__.py +6 -0
- nber_cli-0.1.4/src/nber_cli/core/__init__.py +8 -0
- nber_cli-0.1.4/src/nber_cli/core/download/__init__.py +0 -0
- {nber_cli-0.1.2/src/nber_cli → nber_cli-0.1.4/src/nber_cli/core/download}/downloader.py +32 -19
- nber_cli-0.1.4/src/nber_cli/webui/__init__.py +50 -0
- {nber_cli-0.1.2 → nber_cli-0.1.4}/uv.lock +135 -5
- nber_cli-0.1.2/README.md +0 -39
- nber_cli-0.1.2/src/nber_cli/__init__.py +0 -16
- {nber_cli-0.1.2 → nber_cli-0.1.4}/.github/workflows/publish.yml +0 -0
- {nber_cli-0.1.2 → nber_cli-0.1.4}/.python-version +0 -0
- {nber_cli-0.1.2 → nber_cli-0.1.4}/LICENSE +0 -0
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# Changelog (Auto Generated by Claude Code)
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [0.1.4] - 2025-08-09
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
- Added `--version` / `-v` flag to display current version
|
|
12
|
+
- Added comprehensive help message with examples
|
|
13
|
+
- Added `__main__.py` file to support `python -m nber_cli` usage
|
|
14
|
+
- Added argument grouping for better CLI organization
|
|
15
|
+
- Added automatic help display when no arguments are provided
|
|
16
|
+
|
|
17
|
+
### Changed
|
|
18
|
+
- Improved CLI argument parsing with better error handling
|
|
19
|
+
- Enhanced help text formatting with examples
|
|
20
|
+
- Updated argument structure to use argument groups
|
|
21
|
+
|
|
22
|
+
### Fixed
|
|
23
|
+
- Fixed CLI behavior when no arguments are provided (now shows help instead of error)
|
|
24
|
+
|
|
25
|
+
## [0.1.3] - Previous
|
|
26
|
+
|
|
27
|
+
### Added
|
|
28
|
+
- Initial release with basic NBER paper downloading functionality
|
|
29
|
+
- Support for downloading multiple papers by ID
|
|
30
|
+
- Configurable save path for downloaded papers
|
|
31
|
+
- Command-line interface with download functionality
|
|
32
|
+
- Web UI support via `nber-cli-web` command
|
|
33
|
+
|
|
34
|
+
### Features
|
|
35
|
+
- Async downloading for better performance
|
|
36
|
+
- Support for NBER paper IDs (e.g., w1234, w5678)
|
|
37
|
+
- Default save path: ~/Documents/nber_paper
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: nber-cli
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.4
|
|
4
4
|
Summary: A command-line tool to download NBER papers.
|
|
5
5
|
License-File: LICENSE
|
|
6
6
|
Requires-Python: >=3.11
|
|
@@ -9,10 +9,18 @@ Requires-Dist: aiohttp-retry
|
|
|
9
9
|
Requires-Dist: aiosqlite
|
|
10
10
|
Requires-Dist: certifi
|
|
11
11
|
Requires-Dist: fake-useragent
|
|
12
|
+
Requires-Dist: flask
|
|
12
13
|
Requires-Dist: orjson
|
|
13
14
|
Description-Content-Type: text/markdown
|
|
14
15
|
|
|
15
16
|
# NBER-CLI
|
|
17
|
+
|
|
18
|
+
[](https://opensource.org/licenses/Apache-2.0)
|
|
19
|
+
[](https://pypi.org/project/nber-cli/)
|
|
20
|
+
[](https://pepy.tech/projects/nber-cli)
|
|
21
|
+
[](https://github.com/sepinetam/nber-cli/issues/new)
|
|
22
|
+
[](https://deepwiki.com/SepineTam/nber-cli)
|
|
23
|
+
|
|
16
24
|
NBER-CLI is a command line interface for the National Bureau of Economic Research (NBER) paper data.
|
|
17
25
|
|
|
18
26
|
|
|
@@ -33,21 +41,39 @@ nber-cli --help
|
|
|
33
41
|
|
|
34
42
|
- Download the certain paper to default directory:
|
|
35
43
|
```bash
|
|
36
|
-
nber-cli paper_id
|
|
44
|
+
nber-cli --download paper_id [paper_id ...]
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
- Shorthand:
|
|
48
|
+
```bash
|
|
49
|
+
nber-cli -d paper_id [paper_id ...]
|
|
37
50
|
```
|
|
38
51
|
|
|
39
52
|
- Download the certain paper to a specific directory:
|
|
40
53
|
```bash
|
|
41
|
-
nber-cli paper_id --save_path /path/to/directory
|
|
54
|
+
nber-cli --download paper_id --save_path /path/to/directory
|
|
42
55
|
```
|
|
43
56
|
|
|
44
57
|
An example of downloading a paper with ID `w1234` to the specific directory:
|
|
45
58
|
```bash
|
|
46
59
|
(base) ~/Documents/Github/nber_cli git:[master]
|
|
47
|
-
nber-cli w1234 --save_path ~/Downloads/nber-cli
|
|
60
|
+
nber-cli --download w1234 --save_path ~/Downloads/nber-cli
|
|
48
61
|
2025-06-23 12:00:29,266 - INFO - Loaded 1 ok ids and 0 fail ids from db.
|
|
49
62
|
2025-06-23 12:00:41,097 - INFO - Successfully downloaded w1234 to /Users/sepinetam/Downloads/nber-cli/w1234.pdf
|
|
63
|
+
|
|
50
64
|
```
|
|
51
65
|
|
|
66
|
+
You can also download multiple papers at once:
|
|
67
|
+
```bash
|
|
68
|
+
nber-cli --download w1234 w5678
|
|
69
|
+
```
|
|
70
|
+
## Web UI
|
|
71
|
+
|
|
72
|
+
Start a simple web server with:
|
|
73
|
+
```bash
|
|
74
|
+
nber-cli-web
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
|
|
52
78
|
## LICENSE
|
|
53
79
|
[APACHE-2.0](LICENSE)
|
nber_cli-0.1.4/README.md
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# NBER-CLI
|
|
2
|
+
|
|
3
|
+
[](https://opensource.org/licenses/Apache-2.0)
|
|
4
|
+
[](https://pypi.org/project/nber-cli/)
|
|
5
|
+
[](https://pepy.tech/projects/nber-cli)
|
|
6
|
+
[](https://github.com/sepinetam/nber-cli/issues/new)
|
|
7
|
+
[](https://deepwiki.com/SepineTam/nber-cli)
|
|
8
|
+
|
|
9
|
+
NBER-CLI is a command line interface for the National Bureau of Economic Research (NBER) paper data.
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
## Installation
|
|
13
|
+
```bash
|
|
14
|
+
pip install nber-cli
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
or you can install it from github for the beta version:
|
|
18
|
+
```bash
|
|
19
|
+
pip install git+https://github.com/sepinetam/nber-cli.git
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Usage
|
|
23
|
+
```bash
|
|
24
|
+
nber-cli --help
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
- Download the certain paper to default directory:
|
|
28
|
+
```bash
|
|
29
|
+
nber-cli --download paper_id [paper_id ...]
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
- Shorthand:
|
|
33
|
+
```bash
|
|
34
|
+
nber-cli -d paper_id [paper_id ...]
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
- Download the certain paper to a specific directory:
|
|
38
|
+
```bash
|
|
39
|
+
nber-cli --download paper_id --save_path /path/to/directory
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
An example of downloading a paper with ID `w1234` to the specific directory:
|
|
43
|
+
```bash
|
|
44
|
+
(base) ~/Documents/Github/nber_cli git:[master]
|
|
45
|
+
nber-cli --download w1234 --save_path ~/Downloads/nber-cli
|
|
46
|
+
2025-06-23 12:00:29,266 - INFO - Loaded 1 ok ids and 0 fail ids from db.
|
|
47
|
+
2025-06-23 12:00:41,097 - INFO - Successfully downloaded w1234 to /Users/sepinetam/Downloads/nber-cli/w1234.pdf
|
|
48
|
+
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
You can also download multiple papers at once:
|
|
52
|
+
```bash
|
|
53
|
+
nber-cli --download w1234 w5678
|
|
54
|
+
```
|
|
55
|
+
## Web UI
|
|
56
|
+
|
|
57
|
+
Start a simple web server with:
|
|
58
|
+
```bash
|
|
59
|
+
nber-cli-web
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
## LICENSE
|
|
64
|
+
[APACHE-2.0](LICENSE)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "nber-cli"
|
|
3
|
-
version = "0.1.
|
|
3
|
+
version = "0.1.4"
|
|
4
4
|
description = "A command-line tool to download NBER papers."
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
requires-python = ">=3.11"
|
|
@@ -10,11 +10,13 @@ dependencies = [
|
|
|
10
10
|
"orjson",
|
|
11
11
|
"fake_useragent",
|
|
12
12
|
"aiohttp-retry",
|
|
13
|
-
"certifi"
|
|
13
|
+
"certifi",
|
|
14
|
+
"flask"
|
|
14
15
|
]
|
|
15
16
|
|
|
16
17
|
[project.scripts]
|
|
17
18
|
nber-cli = "nber_cli:main"
|
|
19
|
+
nber-cli-web = "nber_cli.webui:run"
|
|
18
20
|
|
|
19
21
|
[build-system]
|
|
20
22
|
requires = ["hatchling"]
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import argparse
|
|
2
|
+
import asyncio
|
|
3
|
+
import os
|
|
4
|
+
import sys
|
|
5
|
+
from importlib.metadata import version as get_version
|
|
6
|
+
|
|
7
|
+
from .core.download.downloader import main_download_multiple
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def get_version_info() -> str:
|
|
11
|
+
"""Get the version information of the package."""
|
|
12
|
+
try:
|
|
13
|
+
return get_version("nber-cli")
|
|
14
|
+
except Exception:
|
|
15
|
+
return "0.1.3" # Fallback version
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def main():
|
|
19
|
+
parser = argparse.ArgumentParser(
|
|
20
|
+
description="NBER CLI - A command-line tool to download NBER papers.",
|
|
21
|
+
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
22
|
+
epilog="""
|
|
23
|
+
Examples:
|
|
24
|
+
nber-cli -d w1234 w5678
|
|
25
|
+
nber-cli --download w1234 --save_path ./papers
|
|
26
|
+
nber-cli --version
|
|
27
|
+
nber-cli --help
|
|
28
|
+
"""
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
# 添加版本参数
|
|
32
|
+
parser.add_argument(
|
|
33
|
+
"-v",
|
|
34
|
+
"--version",
|
|
35
|
+
action="version",
|
|
36
|
+
version=f"NBER CLI v{get_version_info()}"
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
# 添加下载参数组
|
|
40
|
+
download_group = parser.add_argument_group("Download Options")
|
|
41
|
+
download_group.add_argument(
|
|
42
|
+
"-d",
|
|
43
|
+
"-D",
|
|
44
|
+
"--download",
|
|
45
|
+
dest="paper_ids",
|
|
46
|
+
nargs='+',
|
|
47
|
+
type=str,
|
|
48
|
+
help="One or more NBER paper IDs (e.g., w1234 w5678).")
|
|
49
|
+
download_group.add_argument(
|
|
50
|
+
"--save_path",
|
|
51
|
+
type=str,
|
|
52
|
+
default=os.path.expanduser("~/Documents/nber_paper"),
|
|
53
|
+
help="The directory to save the downloaded paper. Defaults to ~/Documents/nber_paper.")
|
|
54
|
+
|
|
55
|
+
args = parser.parse_args()
|
|
56
|
+
|
|
57
|
+
# 如果没有提供任何参数,显示帮助信息
|
|
58
|
+
if not any(vars(args).values()):
|
|
59
|
+
parser.print_help()
|
|
60
|
+
sys.exit(0)
|
|
61
|
+
|
|
62
|
+
# 如果提供了paper_ids参数,执行下载
|
|
63
|
+
if args.paper_ids:
|
|
64
|
+
asyncio.run(main_download_multiple(args.paper_ids, args.save_path))
|
|
65
|
+
else:
|
|
66
|
+
parser.print_help()
|
|
67
|
+
sys.exit(1)
|
|
File without changes
|
|
@@ -7,21 +7,18 @@
|
|
|
7
7
|
# @Email : sepinetam@gmail.com
|
|
8
8
|
# @File : downloader.py
|
|
9
9
|
|
|
10
|
-
import aiohttp
|
|
11
10
|
import asyncio
|
|
12
|
-
import
|
|
11
|
+
import logging
|
|
13
12
|
import os
|
|
14
|
-
import time
|
|
15
13
|
import random
|
|
16
|
-
import orjson # 比json更快的JSON库
|
|
17
|
-
from fake_useragent import UserAgent
|
|
18
|
-
from typing import List, Set, Dict, Any
|
|
19
|
-
import logging
|
|
20
14
|
import ssl
|
|
15
|
+
import time
|
|
16
|
+
from typing import List
|
|
17
|
+
|
|
18
|
+
import aiosqlite
|
|
21
19
|
import certifi
|
|
22
|
-
from aiohttp_retry import
|
|
23
|
-
import
|
|
24
|
-
import concurrent.futures
|
|
20
|
+
from aiohttp_retry import ExponentialRetry, RetryClient
|
|
21
|
+
from fake_useragent import UserAgent
|
|
25
22
|
|
|
26
23
|
# 设置日志记录
|
|
27
24
|
logging.basicConfig(
|
|
@@ -47,7 +44,8 @@ ID_CACHE = {
|
|
|
47
44
|
|
|
48
45
|
# 创建数据库连接池
|
|
49
46
|
db_pool = None
|
|
50
|
-
DB_PATH = os.path.expanduser("~/.nber_cli_state.db")
|
|
47
|
+
DB_PATH = os.path.expanduser("~/.nber_cli_state.db") # 数据库路径,放在用户主目录下
|
|
48
|
+
|
|
51
49
|
|
|
52
50
|
async def create_db_pool():
|
|
53
51
|
"""创建数据库连接池"""
|
|
@@ -55,16 +53,19 @@ async def create_db_pool():
|
|
|
55
53
|
if db_pool is None:
|
|
56
54
|
db_pool = [await aiosqlite.connect(DB_PATH) for _ in range(DB_POOL_SIZE)]
|
|
57
55
|
|
|
56
|
+
|
|
58
57
|
async def close_db_pool():
|
|
59
58
|
"""关闭数据库连接池"""
|
|
60
59
|
if db_pool:
|
|
61
60
|
for conn in db_pool:
|
|
62
61
|
await conn.close()
|
|
63
62
|
|
|
63
|
+
|
|
64
64
|
async def get_db_conn():
|
|
65
65
|
"""从连接池中获取一个数据库连接"""
|
|
66
66
|
return random.choice(db_pool)
|
|
67
67
|
|
|
68
|
+
|
|
68
69
|
async def init_db():
|
|
69
70
|
"""初始化数据库"""
|
|
70
71
|
conn = await get_db_conn()
|
|
@@ -78,7 +79,8 @@ async def init_db():
|
|
|
78
79
|
)
|
|
79
80
|
await conn.commit()
|
|
80
81
|
finally:
|
|
81
|
-
pass
|
|
82
|
+
pass # 不关闭连接,因为它是从连接池中获取的
|
|
83
|
+
|
|
82
84
|
|
|
83
85
|
async def load_ids_from_db():
|
|
84
86
|
"""从数据库加载已处理的ID到内存缓存"""
|
|
@@ -91,10 +93,12 @@ async def load_ids_from_db():
|
|
|
91
93
|
else:
|
|
92
94
|
ID_CACHE["fail_ids"].add(row[0])
|
|
93
95
|
ID_CACHE["last_update"] = time.time()
|
|
94
|
-
logger.info(
|
|
96
|
+
logger.info(
|
|
97
|
+
f"Loaded {len(ID_CACHE['ok_ids'])} ok ids and {len(ID_CACHE['fail_ids'])} fail ids from db.")
|
|
95
98
|
finally:
|
|
96
99
|
pass
|
|
97
100
|
|
|
101
|
+
|
|
98
102
|
async def get_paper_state(paper_id: str) -> str:
|
|
99
103
|
"""获取特定论文的下载状态"""
|
|
100
104
|
if paper_id in ID_CACHE["ok_ids"]:
|
|
@@ -103,6 +107,7 @@ async def get_paper_state(paper_id: str) -> str:
|
|
|
103
107
|
return "fail"
|
|
104
108
|
return None
|
|
105
109
|
|
|
110
|
+
|
|
106
111
|
async def update_paper_state(paper_id: str, status: str):
|
|
107
112
|
"""更新论文的下载状态"""
|
|
108
113
|
conn = await get_db_conn()
|
|
@@ -123,6 +128,7 @@ async def update_paper_state(paper_id: str, status: str):
|
|
|
123
128
|
finally:
|
|
124
129
|
pass
|
|
125
130
|
|
|
131
|
+
|
|
126
132
|
async def download_paper(paper_id: str, save_path: str):
|
|
127
133
|
"""下载单个NBER论文"""
|
|
128
134
|
filepath = os.path.join(save_path, f"{paper_id}.pdf")
|
|
@@ -135,7 +141,8 @@ async def download_paper(paper_id: str, save_path: str):
|
|
|
135
141
|
logger.info(f"Skipping {paper_id}, already downloaded.")
|
|
136
142
|
return
|
|
137
143
|
if state == 'ok' and not os.path.exists(filepath):
|
|
138
|
-
logger.info(
|
|
144
|
+
logger.info(
|
|
145
|
+
f"{paper_id} marked as downloaded but file missing, re-downloading.")
|
|
139
146
|
|
|
140
147
|
url = f"https://www.nber.org/papers/{paper_id}.pdf"
|
|
141
148
|
|
|
@@ -151,21 +158,27 @@ async def download_paper(paper_id: str, save_path: str):
|
|
|
151
158
|
content = await response.read()
|
|
152
159
|
with open(filepath, 'wb') as f:
|
|
153
160
|
f.write(content)
|
|
154
|
-
logger.info(
|
|
161
|
+
logger.info(
|
|
162
|
+
f"Successfully downloaded {paper_id} to {filepath}")
|
|
155
163
|
await update_paper_state(paper_id, 'ok')
|
|
156
164
|
else:
|
|
157
|
-
logger.error(
|
|
165
|
+
logger.error(
|
|
166
|
+
f"Failed to download {paper_id}, status code: {response.status}")
|
|
158
167
|
await update_paper_state(paper_id, 'fail')
|
|
159
168
|
except Exception as e:
|
|
160
169
|
logger.error(f"An error occurred while downloading {paper_id}: {e}")
|
|
161
170
|
await update_paper_state(paper_id, 'fail')
|
|
162
171
|
|
|
163
|
-
|
|
164
|
-
|
|
172
|
+
|
|
173
|
+
async def main_download_multiple(paper_ids: List[str], save_path: str):
|
|
174
|
+
"""主下载函数,可下载多个paper"""
|
|
165
175
|
await create_db_pool()
|
|
166
176
|
await init_db()
|
|
167
177
|
await load_ids_from_db()
|
|
168
|
-
await download_paper(
|
|
178
|
+
await asyncio.gather(*(download_paper(pid, save_path) for pid in paper_ids))
|
|
169
179
|
await close_db_pool()
|
|
170
180
|
|
|
171
181
|
|
|
182
|
+
async def main_download(paper_id: str, save_path: str):
|
|
183
|
+
"""向后兼容的单文件下载接口"""
|
|
184
|
+
await main_download_multiple([paper_id], save_path)
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import asyncio
|
|
2
|
+
import os
|
|
3
|
+
|
|
4
|
+
from flask import Flask, render_template_string, request
|
|
5
|
+
|
|
6
|
+
from ..core.download.downloader import main_download_multiple
|
|
7
|
+
|
|
8
|
+
DEFAULT_SAVE_PATH = os.path.expanduser("~/Documents/nber_paper")
|
|
9
|
+
app = Flask(__name__)
|
|
10
|
+
|
|
11
|
+
FORM = """
|
|
12
|
+
<!doctype html>
|
|
13
|
+
<html>
|
|
14
|
+
<head>
|
|
15
|
+
<title>NBER CLI Web</title>
|
|
16
|
+
<style>
|
|
17
|
+
body {font-family: Arial, sans-serif; margin: 2em;}
|
|
18
|
+
textarea {width: 100%; height: 6em;}
|
|
19
|
+
.message {color: green;}
|
|
20
|
+
</style>
|
|
21
|
+
</head>
|
|
22
|
+
<body>
|
|
23
|
+
<h1>Download NBER Papers</h1>
|
|
24
|
+
<form method=post>
|
|
25
|
+
<label for="paper_ids">Paper IDs (space or newline separated):</label><br>
|
|
26
|
+
<textarea name="paper_ids" id="paper_ids"></textarea><br>
|
|
27
|
+
<input type=submit value=Download>
|
|
28
|
+
</form>
|
|
29
|
+
<p class="message">{{message}}</p>
|
|
30
|
+
</body>
|
|
31
|
+
</html>
|
|
32
|
+
"""
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
@app.route('/', methods=['GET', 'POST'])
|
|
36
|
+
def index():
|
|
37
|
+
message = ''
|
|
38
|
+
if request.method == 'POST':
|
|
39
|
+
ids_raw = request.form.get('paper_ids', '')
|
|
40
|
+
paper_ids = [pid.strip() for pid in ids_raw.split() if pid.strip()]
|
|
41
|
+
if paper_ids:
|
|
42
|
+
asyncio.run(main_download_multiple(paper_ids, DEFAULT_SAVE_PATH))
|
|
43
|
+
message = f"Downloaded {', '.join(paper_ids)}"
|
|
44
|
+
else:
|
|
45
|
+
message = 'Please enter at least one paper ID.'
|
|
46
|
+
return render_template_string(FORM, message=message)
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def run():
|
|
50
|
+
app.run()
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
version = 1
|
|
2
|
-
revision =
|
|
2
|
+
revision = 3
|
|
3
3
|
requires-python = ">=3.11"
|
|
4
4
|
|
|
5
5
|
[[package]]
|
|
@@ -124,13 +124,43 @@ wheels = [
|
|
|
124
124
|
{ url = "https://files.pythonhosted.org/packages/77/06/bb80f5f86020c4551da315d78b3ab75e8228f89f0162f2c3a819e407941a/attrs-25.3.0-py3-none-any.whl", hash = "sha256:427318ce031701fea540783410126f03899a97ffc6f61596ad581ac2e40e3bc3", size = 63815, upload-time = "2025-03-13T11:10:21.14Z" },
|
|
125
125
|
]
|
|
126
126
|
|
|
127
|
+
[[package]]
|
|
128
|
+
name = "blinker"
|
|
129
|
+
version = "1.9.0"
|
|
130
|
+
source = { registry = "https://pypi.org/simple" }
|
|
131
|
+
sdist = { url = "https://files.pythonhosted.org/packages/21/28/9b3f50ce0e048515135495f198351908d99540d69bfdc8c1d15b73dc55ce/blinker-1.9.0.tar.gz", hash = "sha256:b4ce2265a7abece45e7cc896e98dbebe6cead56bcf805a3d23136d145f5445bf", size = 22460, upload-time = "2024-11-08T17:25:47.436Z" }
|
|
132
|
+
wheels = [
|
|
133
|
+
{ url = "https://files.pythonhosted.org/packages/10/cb/f2ad4230dc2eb1a74edf38f1a38b9b52277f75bef262d8908e60d957e13c/blinker-1.9.0-py3-none-any.whl", hash = "sha256:ba0efaa9080b619ff2f3459d1d500c57bddea4a6b424b60a91141db6fd2f08bc", size = 8458, upload-time = "2024-11-08T17:25:46.184Z" },
|
|
134
|
+
]
|
|
135
|
+
|
|
127
136
|
[[package]]
|
|
128
137
|
name = "certifi"
|
|
129
|
-
version = "2025.
|
|
138
|
+
version = "2025.8.3"
|
|
130
139
|
source = { registry = "https://pypi.org/simple" }
|
|
131
|
-
sdist = { url = "https://files.pythonhosted.org/packages/
|
|
140
|
+
sdist = { url = "https://files.pythonhosted.org/packages/dc/67/960ebe6bf230a96cda2e0abcf73af550ec4f090005363542f0765df162e0/certifi-2025.8.3.tar.gz", hash = "sha256:e564105f78ded564e3ae7c923924435e1daa7463faeab5bb932bc53ffae63407", size = 162386, upload-time = "2025-08-03T03:07:47.08Z" }
|
|
132
141
|
wheels = [
|
|
133
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
142
|
+
{ url = "https://files.pythonhosted.org/packages/e5/48/1549795ba7742c948d2ad169c1c8cdbae65bc450d6cd753d124b17c8cd32/certifi-2025.8.3-py3-none-any.whl", hash = "sha256:f6c12493cfb1b06ba2ff328595af9350c65d6644968e5d3a2ffd78699af217a5", size = 161216, upload-time = "2025-08-03T03:07:45.777Z" },
|
|
143
|
+
]
|
|
144
|
+
|
|
145
|
+
[[package]]
|
|
146
|
+
name = "click"
|
|
147
|
+
version = "8.2.1"
|
|
148
|
+
source = { registry = "https://pypi.org/simple" }
|
|
149
|
+
dependencies = [
|
|
150
|
+
{ name = "colorama", marker = "sys_platform == 'win32'" },
|
|
151
|
+
]
|
|
152
|
+
sdist = { url = "https://files.pythonhosted.org/packages/60/6c/8ca2efa64cf75a977a0d7fac081354553ebe483345c734fb6b6515d96bbc/click-8.2.1.tar.gz", hash = "sha256:27c491cc05d968d271d5a1db13e3b5a184636d9d930f148c50b038f0d0646202", size = 286342, upload-time = "2025-05-20T23:19:49.832Z" }
|
|
153
|
+
wheels = [
|
|
154
|
+
{ url = "https://files.pythonhosted.org/packages/85/32/10bb5764d90a8eee674e9dc6f4db6a0ab47c8c4d0d83c27f7c39ac415a4d/click-8.2.1-py3-none-any.whl", hash = "sha256:61a3265b914e850b85317d0b3109c7f8cd35a670f963866005d6ef1d5175a12b", size = 102215, upload-time = "2025-05-20T23:19:47.796Z" },
|
|
155
|
+
]
|
|
156
|
+
|
|
157
|
+
[[package]]
|
|
158
|
+
name = "colorama"
|
|
159
|
+
version = "0.4.6"
|
|
160
|
+
source = { registry = "https://pypi.org/simple" }
|
|
161
|
+
sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697, upload-time = "2022-10-25T02:36:22.414Z" }
|
|
162
|
+
wheels = [
|
|
163
|
+
{ url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" },
|
|
134
164
|
]
|
|
135
165
|
|
|
136
166
|
[[package]]
|
|
@@ -142,6 +172,23 @@ wheels = [
|
|
|
142
172
|
{ url = "https://files.pythonhosted.org/packages/51/37/b3ea9cd5558ff4cb51957caca2193981c6b0ff30bd0d2630ac62505d99d0/fake_useragent-2.2.0-py3-none-any.whl", hash = "sha256:67f35ca4d847b0d298187443aaf020413746e56acd985a611908c73dba2daa24", size = 161695, upload-time = "2025-04-14T15:32:17.732Z" },
|
|
143
173
|
]
|
|
144
174
|
|
|
175
|
+
[[package]]
|
|
176
|
+
name = "flask"
|
|
177
|
+
version = "3.1.1"
|
|
178
|
+
source = { registry = "https://pypi.org/simple" }
|
|
179
|
+
dependencies = [
|
|
180
|
+
{ name = "blinker" },
|
|
181
|
+
{ name = "click" },
|
|
182
|
+
{ name = "itsdangerous" },
|
|
183
|
+
{ name = "jinja2" },
|
|
184
|
+
{ name = "markupsafe" },
|
|
185
|
+
{ name = "werkzeug" },
|
|
186
|
+
]
|
|
187
|
+
sdist = { url = "https://files.pythonhosted.org/packages/c0/de/e47735752347f4128bcf354e0da07ef311a78244eba9e3dc1d4a5ab21a98/flask-3.1.1.tar.gz", hash = "sha256:284c7b8f2f58cb737f0cf1c30fd7eaf0ccfcde196099d24ecede3fc2005aa59e", size = 753440, upload-time = "2025-05-13T15:01:17.447Z" }
|
|
188
|
+
wheels = [
|
|
189
|
+
{ url = "https://files.pythonhosted.org/packages/3d/68/9d4508e893976286d2ead7f8f571314af6c2037af34853a30fd769c02e9d/flask-3.1.1-py3-none-any.whl", hash = "sha256:07aae2bb5eaf77993ef57e357491839f5fd9f4dc281593a81a9e4d79a24f295c", size = 103305, upload-time = "2025-05-13T15:01:15.591Z" },
|
|
190
|
+
]
|
|
191
|
+
|
|
145
192
|
[[package]]
|
|
146
193
|
name = "frozenlist"
|
|
147
194
|
version = "1.7.0"
|
|
@@ -228,6 +275,75 @@ wheels = [
|
|
|
228
275
|
{ url = "https://files.pythonhosted.org/packages/76/c6/c88e154df9c4e1a2a66ccf0005a88dfb2650c1dffb6f5ce603dfbd452ce3/idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3", size = 70442, upload-time = "2024-09-15T18:07:37.964Z" },
|
|
229
276
|
]
|
|
230
277
|
|
|
278
|
+
[[package]]
|
|
279
|
+
name = "itsdangerous"
|
|
280
|
+
version = "2.2.0"
|
|
281
|
+
source = { registry = "https://pypi.org/simple" }
|
|
282
|
+
sdist = { url = "https://files.pythonhosted.org/packages/9c/cb/8ac0172223afbccb63986cc25049b154ecfb5e85932587206f42317be31d/itsdangerous-2.2.0.tar.gz", hash = "sha256:e0050c0b7da1eea53ffaf149c0cfbb5c6e2e2b69c4bef22c81fa6eb73e5f6173", size = 54410, upload-time = "2024-04-16T21:28:15.614Z" }
|
|
283
|
+
wheels = [
|
|
284
|
+
{ url = "https://files.pythonhosted.org/packages/04/96/92447566d16df59b2a776c0fb82dbc4d9e07cd95062562af01e408583fc4/itsdangerous-2.2.0-py3-none-any.whl", hash = "sha256:c6242fc49e35958c8b15141343aa660db5fc54d4f13a1db01a3f5891b98700ef", size = 16234, upload-time = "2024-04-16T21:28:14.499Z" },
|
|
285
|
+
]
|
|
286
|
+
|
|
287
|
+
[[package]]
|
|
288
|
+
name = "jinja2"
|
|
289
|
+
version = "3.1.6"
|
|
290
|
+
source = { registry = "https://pypi.org/simple" }
|
|
291
|
+
dependencies = [
|
|
292
|
+
{ name = "markupsafe" },
|
|
293
|
+
]
|
|
294
|
+
sdist = { url = "https://files.pythonhosted.org/packages/df/bf/f7da0350254c0ed7c72f3e33cef02e048281fec7ecec5f032d4aac52226b/jinja2-3.1.6.tar.gz", hash = "sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d", size = 245115, upload-time = "2025-03-05T20:05:02.478Z" }
|
|
295
|
+
wheels = [
|
|
296
|
+
{ url = "https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl", hash = "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67", size = 134899, upload-time = "2025-03-05T20:05:00.369Z" },
|
|
297
|
+
]
|
|
298
|
+
|
|
299
|
+
[[package]]
|
|
300
|
+
name = "markupsafe"
|
|
301
|
+
version = "3.0.2"
|
|
302
|
+
source = { registry = "https://pypi.org/simple" }
|
|
303
|
+
sdist = { url = "https://files.pythonhosted.org/packages/b2/97/5d42485e71dfc078108a86d6de8fa46db44a1a9295e89c5d6d4a06e23a62/markupsafe-3.0.2.tar.gz", hash = "sha256:ee55d3edf80167e48ea11a923c7386f4669df67d7994554387f84e7d8b0a2bf0", size = 20537, upload-time = "2024-10-18T15:21:54.129Z" }
|
|
304
|
+
wheels = [
|
|
305
|
+
{ url = "https://files.pythonhosted.org/packages/6b/28/bbf83e3f76936960b850435576dd5e67034e200469571be53f69174a2dfd/MarkupSafe-3.0.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9025b4018f3a1314059769c7bf15441064b2207cb3f065e6ea1e7359cb46db9d", size = 14353, upload-time = "2024-10-18T15:21:02.187Z" },
|
|
306
|
+
{ url = "https://files.pythonhosted.org/packages/6c/30/316d194b093cde57d448a4c3209f22e3046c5bb2fb0820b118292b334be7/MarkupSafe-3.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:93335ca3812df2f366e80509ae119189886b0f3c2b81325d39efdb84a1e2ae93", size = 12392, upload-time = "2024-10-18T15:21:02.941Z" },
|
|
307
|
+
{ url = "https://files.pythonhosted.org/packages/f2/96/9cdafba8445d3a53cae530aaf83c38ec64c4d5427d975c974084af5bc5d2/MarkupSafe-3.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2cb8438c3cbb25e220c2ab33bb226559e7afb3baec11c4f218ffa7308603c832", size = 23984, upload-time = "2024-10-18T15:21:03.953Z" },
|
|
308
|
+
{ url = "https://files.pythonhosted.org/packages/f1/a4/aefb044a2cd8d7334c8a47d3fb2c9f328ac48cb349468cc31c20b539305f/MarkupSafe-3.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a123e330ef0853c6e822384873bef7507557d8e4a082961e1defa947aa59ba84", size = 23120, upload-time = "2024-10-18T15:21:06.495Z" },
|
|
309
|
+
{ url = "https://files.pythonhosted.org/packages/8d/21/5e4851379f88f3fad1de30361db501300d4f07bcad047d3cb0449fc51f8c/MarkupSafe-3.0.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1e084f686b92e5b83186b07e8a17fc09e38fff551f3602b249881fec658d3eca", size = 23032, upload-time = "2024-10-18T15:21:07.295Z" },
|
|
310
|
+
{ url = "https://files.pythonhosted.org/packages/00/7b/e92c64e079b2d0d7ddf69899c98842f3f9a60a1ae72657c89ce2655c999d/MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d8213e09c917a951de9d09ecee036d5c7d36cb6cb7dbaece4c71a60d79fb9798", size = 24057, upload-time = "2024-10-18T15:21:08.073Z" },
|
|
311
|
+
{ url = "https://files.pythonhosted.org/packages/f9/ac/46f960ca323037caa0a10662ef97d0a4728e890334fc156b9f9e52bcc4ca/MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:5b02fb34468b6aaa40dfc198d813a641e3a63b98c2b05a16b9f80b7ec314185e", size = 23359, upload-time = "2024-10-18T15:21:09.318Z" },
|
|
312
|
+
{ url = "https://files.pythonhosted.org/packages/69/84/83439e16197337b8b14b6a5b9c2105fff81d42c2a7c5b58ac7b62ee2c3b1/MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:0bff5e0ae4ef2e1ae4fdf2dfd5b76c75e5c2fa4132d05fc1b0dabcd20c7e28c4", size = 23306, upload-time = "2024-10-18T15:21:10.185Z" },
|
|
313
|
+
{ url = "https://files.pythonhosted.org/packages/9a/34/a15aa69f01e2181ed8d2b685c0d2f6655d5cca2c4db0ddea775e631918cd/MarkupSafe-3.0.2-cp311-cp311-win32.whl", hash = "sha256:6c89876f41da747c8d3677a2b540fb32ef5715f97b66eeb0c6b66f5e3ef6f59d", size = 15094, upload-time = "2024-10-18T15:21:11.005Z" },
|
|
314
|
+
{ url = "https://files.pythonhosted.org/packages/da/b8/3a3bd761922d416f3dc5d00bfbed11f66b1ab89a0c2b6e887240a30b0f6b/MarkupSafe-3.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:70a87b411535ccad5ef2f1df5136506a10775d267e197e4cf531ced10537bd6b", size = 15521, upload-time = "2024-10-18T15:21:12.911Z" },
|
|
315
|
+
{ url = "https://files.pythonhosted.org/packages/22/09/d1f21434c97fc42f09d290cbb6350d44eb12f09cc62c9476effdb33a18aa/MarkupSafe-3.0.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:9778bd8ab0a994ebf6f84c2b949e65736d5575320a17ae8984a77fab08db94cf", size = 14274, upload-time = "2024-10-18T15:21:13.777Z" },
|
|
316
|
+
{ url = "https://files.pythonhosted.org/packages/6b/b0/18f76bba336fa5aecf79d45dcd6c806c280ec44538b3c13671d49099fdd0/MarkupSafe-3.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:846ade7b71e3536c4e56b386c2a47adf5741d2d8b94ec9dc3e92e5e1ee1e2225", size = 12348, upload-time = "2024-10-18T15:21:14.822Z" },
|
|
317
|
+
{ url = "https://files.pythonhosted.org/packages/e0/25/dd5c0f6ac1311e9b40f4af06c78efde0f3b5cbf02502f8ef9501294c425b/MarkupSafe-3.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1c99d261bd2d5f6b59325c92c73df481e05e57f19837bdca8413b9eac4bd8028", size = 24149, upload-time = "2024-10-18T15:21:15.642Z" },
|
|
318
|
+
{ url = "https://files.pythonhosted.org/packages/f3/f0/89e7aadfb3749d0f52234a0c8c7867877876e0a20b60e2188e9850794c17/MarkupSafe-3.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e17c96c14e19278594aa4841ec148115f9c7615a47382ecb6b82bd8fea3ab0c8", size = 23118, upload-time = "2024-10-18T15:21:17.133Z" },
|
|
319
|
+
{ url = "https://files.pythonhosted.org/packages/d5/da/f2eeb64c723f5e3777bc081da884b414671982008c47dcc1873d81f625b6/MarkupSafe-3.0.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:88416bd1e65dcea10bc7569faacb2c20ce071dd1f87539ca2ab364bf6231393c", size = 22993, upload-time = "2024-10-18T15:21:18.064Z" },
|
|
320
|
+
{ url = "https://files.pythonhosted.org/packages/da/0e/1f32af846df486dce7c227fe0f2398dc7e2e51d4a370508281f3c1c5cddc/MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:2181e67807fc2fa785d0592dc2d6206c019b9502410671cc905d132a92866557", size = 24178, upload-time = "2024-10-18T15:21:18.859Z" },
|
|
321
|
+
{ url = "https://files.pythonhosted.org/packages/c4/f6/bb3ca0532de8086cbff5f06d137064c8410d10779c4c127e0e47d17c0b71/MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:52305740fe773d09cffb16f8ed0427942901f00adedac82ec8b67752f58a1b22", size = 23319, upload-time = "2024-10-18T15:21:19.671Z" },
|
|
322
|
+
{ url = "https://files.pythonhosted.org/packages/a2/82/8be4c96ffee03c5b4a034e60a31294daf481e12c7c43ab8e34a1453ee48b/MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ad10d3ded218f1039f11a75f8091880239651b52e9bb592ca27de44eed242a48", size = 23352, upload-time = "2024-10-18T15:21:20.971Z" },
|
|
323
|
+
{ url = "https://files.pythonhosted.org/packages/51/ae/97827349d3fcffee7e184bdf7f41cd6b88d9919c80f0263ba7acd1bbcb18/MarkupSafe-3.0.2-cp312-cp312-win32.whl", hash = "sha256:0f4ca02bea9a23221c0182836703cbf8930c5e9454bacce27e767509fa286a30", size = 15097, upload-time = "2024-10-18T15:21:22.646Z" },
|
|
324
|
+
{ url = "https://files.pythonhosted.org/packages/c1/80/a61f99dc3a936413c3ee4e1eecac96c0da5ed07ad56fd975f1a9da5bc630/MarkupSafe-3.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:8e06879fc22a25ca47312fbe7c8264eb0b662f6db27cb2d3bbbc74b1df4b9b87", size = 15601, upload-time = "2024-10-18T15:21:23.499Z" },
|
|
325
|
+
{ url = "https://files.pythonhosted.org/packages/83/0e/67eb10a7ecc77a0c2bbe2b0235765b98d164d81600746914bebada795e97/MarkupSafe-3.0.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ba9527cdd4c926ed0760bc301f6728ef34d841f405abf9d4f959c478421e4efd", size = 14274, upload-time = "2024-10-18T15:21:24.577Z" },
|
|
326
|
+
{ url = "https://files.pythonhosted.org/packages/2b/6d/9409f3684d3335375d04e5f05744dfe7e9f120062c9857df4ab490a1031a/MarkupSafe-3.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f8b3d067f2e40fe93e1ccdd6b2e1d16c43140e76f02fb1319a05cf2b79d99430", size = 12352, upload-time = "2024-10-18T15:21:25.382Z" },
|
|
327
|
+
{ url = "https://files.pythonhosted.org/packages/d2/f5/6eadfcd3885ea85fe2a7c128315cc1bb7241e1987443d78c8fe712d03091/MarkupSafe-3.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:569511d3b58c8791ab4c2e1285575265991e6d8f8700c7be0e88f86cb0672094", size = 24122, upload-time = "2024-10-18T15:21:26.199Z" },
|
|
328
|
+
{ url = "https://files.pythonhosted.org/packages/0c/91/96cf928db8236f1bfab6ce15ad070dfdd02ed88261c2afafd4b43575e9e9/MarkupSafe-3.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:15ab75ef81add55874e7ab7055e9c397312385bd9ced94920f2802310c930396", size = 23085, upload-time = "2024-10-18T15:21:27.029Z" },
|
|
329
|
+
{ url = "https://files.pythonhosted.org/packages/c2/cf/c9d56af24d56ea04daae7ac0940232d31d5a8354f2b457c6d856b2057d69/MarkupSafe-3.0.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f3818cb119498c0678015754eba762e0d61e5b52d34c8b13d770f0719f7b1d79", size = 22978, upload-time = "2024-10-18T15:21:27.846Z" },
|
|
330
|
+
{ url = "https://files.pythonhosted.org/packages/2a/9f/8619835cd6a711d6272d62abb78c033bda638fdc54c4e7f4272cf1c0962b/MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:cdb82a876c47801bb54a690c5ae105a46b392ac6099881cdfb9f6e95e4014c6a", size = 24208, upload-time = "2024-10-18T15:21:28.744Z" },
|
|
331
|
+
{ url = "https://files.pythonhosted.org/packages/f9/bf/176950a1792b2cd2102b8ffeb5133e1ed984547b75db47c25a67d3359f77/MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:cabc348d87e913db6ab4aa100f01b08f481097838bdddf7c7a84b7575b7309ca", size = 23357, upload-time = "2024-10-18T15:21:29.545Z" },
|
|
332
|
+
{ url = "https://files.pythonhosted.org/packages/ce/4f/9a02c1d335caabe5c4efb90e1b6e8ee944aa245c1aaaab8e8a618987d816/MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:444dcda765c8a838eaae23112db52f1efaf750daddb2d9ca300bcae1039adc5c", size = 23344, upload-time = "2024-10-18T15:21:30.366Z" },
|
|
333
|
+
{ url = "https://files.pythonhosted.org/packages/ee/55/c271b57db36f748f0e04a759ace9f8f759ccf22b4960c270c78a394f58be/MarkupSafe-3.0.2-cp313-cp313-win32.whl", hash = "sha256:bcf3e58998965654fdaff38e58584d8937aa3096ab5354d493c77d1fdd66d7a1", size = 15101, upload-time = "2024-10-18T15:21:31.207Z" },
|
|
334
|
+
{ url = "https://files.pythonhosted.org/packages/29/88/07df22d2dd4df40aba9f3e402e6dc1b8ee86297dddbad4872bd5e7b0094f/MarkupSafe-3.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:e6a2a455bd412959b57a172ce6328d2dd1f01cb2135efda2e4576e8a23fa3b0f", size = 15603, upload-time = "2024-10-18T15:21:32.032Z" },
|
|
335
|
+
{ url = "https://files.pythonhosted.org/packages/62/6a/8b89d24db2d32d433dffcd6a8779159da109842434f1dd2f6e71f32f738c/MarkupSafe-3.0.2-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:b5a6b3ada725cea8a5e634536b1b01c30bcdcd7f9c6fff4151548d5bf6b3a36c", size = 14510, upload-time = "2024-10-18T15:21:33.625Z" },
|
|
336
|
+
{ url = "https://files.pythonhosted.org/packages/7a/06/a10f955f70a2e5a9bf78d11a161029d278eeacbd35ef806c3fd17b13060d/MarkupSafe-3.0.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:a904af0a6162c73e3edcb969eeeb53a63ceeb5d8cf642fade7d39e7963a22ddb", size = 12486, upload-time = "2024-10-18T15:21:34.611Z" },
|
|
337
|
+
{ url = "https://files.pythonhosted.org/packages/34/cf/65d4a571869a1a9078198ca28f39fba5fbb910f952f9dbc5220afff9f5e6/MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4aa4e5faecf353ed117801a068ebab7b7e09ffb6e1d5e412dc852e0da018126c", size = 25480, upload-time = "2024-10-18T15:21:35.398Z" },
|
|
338
|
+
{ url = "https://files.pythonhosted.org/packages/0c/e3/90e9651924c430b885468b56b3d597cabf6d72be4b24a0acd1fa0e12af67/MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c0ef13eaeee5b615fb07c9a7dadb38eac06a0608b41570d8ade51c56539e509d", size = 23914, upload-time = "2024-10-18T15:21:36.231Z" },
|
|
339
|
+
{ url = "https://files.pythonhosted.org/packages/66/8c/6c7cf61f95d63bb866db39085150df1f2a5bd3335298f14a66b48e92659c/MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d16a81a06776313e817c951135cf7340a3e91e8c1ff2fac444cfd75fffa04afe", size = 23796, upload-time = "2024-10-18T15:21:37.073Z" },
|
|
340
|
+
{ url = "https://files.pythonhosted.org/packages/bb/35/cbe9238ec3f47ac9a7c8b3df7a808e7cb50fe149dc7039f5f454b3fba218/MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:6381026f158fdb7c72a168278597a5e3a5222e83ea18f543112b2662a9b699c5", size = 25473, upload-time = "2024-10-18T15:21:37.932Z" },
|
|
341
|
+
{ url = "https://files.pythonhosted.org/packages/e6/32/7621a4382488aa283cc05e8984a9c219abad3bca087be9ec77e89939ded9/MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:3d79d162e7be8f996986c064d1c7c817f6df3a77fe3d6859f6f9e7be4b8c213a", size = 24114, upload-time = "2024-10-18T15:21:39.799Z" },
|
|
342
|
+
{ url = "https://files.pythonhosted.org/packages/0d/80/0985960e4b89922cb5a0bac0ed39c5b96cbc1a536a99f30e8c220a996ed9/MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:131a3c7689c85f5ad20f9f6fb1b866f402c445b220c19fe4308c0b147ccd2ad9", size = 24098, upload-time = "2024-10-18T15:21:40.813Z" },
|
|
343
|
+
{ url = "https://files.pythonhosted.org/packages/82/78/fedb03c7d5380df2427038ec8d973587e90561b2d90cd472ce9254cf348b/MarkupSafe-3.0.2-cp313-cp313t-win32.whl", hash = "sha256:ba8062ed2cf21c07a9e295d5b8a2a5ce678b913b45fdf68c32d95d6c1291e0b6", size = 15208, upload-time = "2024-10-18T15:21:41.814Z" },
|
|
344
|
+
{ url = "https://files.pythonhosted.org/packages/4f/65/6079a46068dfceaeabb5dcad6d674f5f5c61a6fa5673746f42a9f4c233b3/MarkupSafe-3.0.2-cp313-cp313t-win_amd64.whl", hash = "sha256:e444a31f8db13eb18ada366ab3cf45fd4b31e4db1236a4448f68778c1d1a5a2f", size = 15739, upload-time = "2024-10-18T15:21:42.784Z" },
|
|
345
|
+
]
|
|
346
|
+
|
|
231
347
|
[[package]]
|
|
232
348
|
name = "multidict"
|
|
233
349
|
version = "6.5.0"
|
|
@@ -311,7 +427,7 @@ wheels = [
|
|
|
311
427
|
|
|
312
428
|
[[package]]
|
|
313
429
|
name = "nber-cli"
|
|
314
|
-
version = "0.1.
|
|
430
|
+
version = "0.1.4"
|
|
315
431
|
source = { editable = "." }
|
|
316
432
|
dependencies = [
|
|
317
433
|
{ name = "aiohttp" },
|
|
@@ -319,6 +435,7 @@ dependencies = [
|
|
|
319
435
|
{ name = "aiosqlite" },
|
|
320
436
|
{ name = "certifi" },
|
|
321
437
|
{ name = "fake-useragent" },
|
|
438
|
+
{ name = "flask" },
|
|
322
439
|
{ name = "orjson" },
|
|
323
440
|
]
|
|
324
441
|
|
|
@@ -329,6 +446,7 @@ requires-dist = [
|
|
|
329
446
|
{ name = "aiosqlite" },
|
|
330
447
|
{ name = "certifi" },
|
|
331
448
|
{ name = "fake-useragent" },
|
|
449
|
+
{ name = "flask" },
|
|
332
450
|
{ name = "orjson" },
|
|
333
451
|
]
|
|
334
452
|
|
|
@@ -467,6 +585,18 @@ wheels = [
|
|
|
467
585
|
{ url = "https://files.pythonhosted.org/packages/69/e0/552843e0d356fbb5256d21449fa957fa4eff3bbc135a74a691ee70c7c5da/typing_extensions-4.14.0-py3-none-any.whl", hash = "sha256:a1514509136dd0b477638fc68d6a91497af5076466ad0fa6c338e44e359944af", size = 43839, upload-time = "2025-06-02T14:52:10.026Z" },
|
|
468
586
|
]
|
|
469
587
|
|
|
588
|
+
[[package]]
|
|
589
|
+
name = "werkzeug"
|
|
590
|
+
version = "3.1.3"
|
|
591
|
+
source = { registry = "https://pypi.org/simple" }
|
|
592
|
+
dependencies = [
|
|
593
|
+
{ name = "markupsafe" },
|
|
594
|
+
]
|
|
595
|
+
sdist = { url = "https://files.pythonhosted.org/packages/9f/69/83029f1f6300c5fb2471d621ab06f6ec6b3324685a2ce0f9777fd4a8b71e/werkzeug-3.1.3.tar.gz", hash = "sha256:60723ce945c19328679790e3282cc758aa4a6040e4bb330f53d30fa546d44746", size = 806925, upload-time = "2024-11-08T15:52:18.093Z" }
|
|
596
|
+
wheels = [
|
|
597
|
+
{ url = "https://files.pythonhosted.org/packages/52/24/ab44c871b0f07f491e5d2ad12c9bd7358e527510618cb1b803a88e986db1/werkzeug-3.1.3-py3-none-any.whl", hash = "sha256:54b78bf3716d19a65be4fceccc0d1d7b89e608834989dfae50ea87564639213e", size = 224498, upload-time = "2024-11-08T15:52:16.132Z" },
|
|
598
|
+
]
|
|
599
|
+
|
|
470
600
|
[[package]]
|
|
471
601
|
name = "yarl"
|
|
472
602
|
version = "1.20.1"
|
nber_cli-0.1.2/README.md
DELETED
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
# NBER-CLI
|
|
2
|
-
NBER-CLI is a command line interface for the National Bureau of Economic Research (NBER) paper data.
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
## Installation
|
|
6
|
-
```bash
|
|
7
|
-
pip install nber-cli
|
|
8
|
-
```
|
|
9
|
-
|
|
10
|
-
or you can install it from github for the beta version:
|
|
11
|
-
```bash
|
|
12
|
-
pip install git+https://github.com/sepinetam/nber-cli.git
|
|
13
|
-
```
|
|
14
|
-
|
|
15
|
-
## Usage
|
|
16
|
-
```bash
|
|
17
|
-
nber-cli --help
|
|
18
|
-
```
|
|
19
|
-
|
|
20
|
-
- Download the certain paper to default directory:
|
|
21
|
-
```bash
|
|
22
|
-
nber-cli paper_id
|
|
23
|
-
```
|
|
24
|
-
|
|
25
|
-
- Download the certain paper to a specific directory:
|
|
26
|
-
```bash
|
|
27
|
-
nber-cli paper_id --save_path /path/to/directory
|
|
28
|
-
```
|
|
29
|
-
|
|
30
|
-
An example of downloading a paper with ID `w1234` to the specific directory:
|
|
31
|
-
```bash
|
|
32
|
-
(base) ~/Documents/Github/nber_cli git:[master]
|
|
33
|
-
nber-cli w1234 --save_path ~/Downloads/nber-cli
|
|
34
|
-
2025-06-23 12:00:29,266 - INFO - Loaded 1 ok ids and 0 fail ids from db.
|
|
35
|
-
2025-06-23 12:00:41,097 - INFO - Successfully downloaded w1234 to /Users/sepinetam/Downloads/nber-cli/w1234.pdf
|
|
36
|
-
```
|
|
37
|
-
|
|
38
|
-
## LICENSE
|
|
39
|
-
[APACHE-2.0](LICENSE)
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import argparse
|
|
2
|
-
import asyncio
|
|
3
|
-
import os
|
|
4
|
-
from .downloader import main_download
|
|
5
|
-
|
|
6
|
-
def main():
|
|
7
|
-
parser = argparse.ArgumentParser(description="Download NBER papers.")
|
|
8
|
-
parser.add_argument("paper_id", type=str, help="The NBER paper ID (e.g., w1234).")
|
|
9
|
-
parser.add_argument("--save_path", type=str, default=os.path.expanduser("~/Documents/nber_paper"),
|
|
10
|
-
help="The directory to save the downloaded paper. Defaults to ~/Documents/nber_paper.")
|
|
11
|
-
|
|
12
|
-
args = parser.parse_args()
|
|
13
|
-
|
|
14
|
-
asyncio.run(main_download(args.paper_id, args.save_path))
|
|
15
|
-
|
|
16
|
-
|
|
File without changes
|
|
File without changes
|
|
File without changes
|