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.
@@ -6,6 +6,8 @@ dist/
6
6
  wheels/
7
7
  *.egg-info
8
8
 
9
+ release/
10
+
9
11
  # Virtual environments
10
12
  .venv
11
13
 
@@ -17,3 +19,6 @@ wheels/
17
19
 
18
20
  # OS X
19
21
  *.DS_Store
22
+
23
+ # local files
24
+ *.local.*
@@ -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.2
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
+ [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)
19
+ [![PyPI version](https://img.shields.io/pypi/v/nber-cli.svg)](https://pypi.org/project/nber-cli/)
20
+ [![PyPI Downloads](https://static.pepy.tech/badge/nber-cli)](https://pepy.tech/projects/nber-cli)
21
+ [![Issue](https://img.shields.io/badge/Issue-report-green.svg)](https://github.com/sepinetam/nber-cli/issues/new)
22
+ [![Ask DeepWiki](https://deepwiki.com/badge.svg)](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)
@@ -0,0 +1,64 @@
1
+ # NBER-CLI
2
+
3
+ [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)
4
+ [![PyPI version](https://img.shields.io/pypi/v/nber-cli.svg)](https://pypi.org/project/nber-cli/)
5
+ [![PyPI Downloads](https://static.pepy.tech/badge/nber-cli)](https://pepy.tech/projects/nber-cli)
6
+ [![Issue](https://img.shields.io/badge/Issue-report-green.svg)](https://github.com/sepinetam/nber-cli/issues/new)
7
+ [![Ask DeepWiki](https://deepwiki.com/badge.svg)](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.2"
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)
@@ -0,0 +1,6 @@
1
+ """Entry point for the nber-cli package."""
2
+
3
+ from . import main
4
+
5
+ if __name__ == "__main__":
6
+ main()
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/python3
2
+ # -*- coding: utf-8 -*-
3
+ #
4
+ # Copyright (C) 2025 - Present Sepine Tam, Inc. All Rights Reserved
5
+ #
6
+ # @Author : Sepine Tam
7
+ # @Email : sepinetam@gmail.com
8
+ # @File : __init__.py.py
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 aiosqlite
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 RetryClient, ExponentialRetry
23
- import functools
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(f"Loaded {len(ID_CACHE['ok_ids'])} ok ids and {len(ID_CACHE['fail_ids'])} fail ids from db.")
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(f"{paper_id} marked as downloaded but file missing, re-downloading.")
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(f"Successfully downloaded {paper_id} to {filepath}")
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(f"Failed to download {paper_id}, status code: {response.status}")
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
- async def main_download(paper_id: str, save_path: str):
164
- """主下载函数,用于CLI调用"""
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(paper_id, save_path)
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
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.6.15"
138
+ version = "2025.8.3"
130
139
  source = { registry = "https://pypi.org/simple" }
131
- sdist = { url = "https://files.pythonhosted.org/packages/73/f7/f14b46d4bcd21092d7d3ccef689615220d8a08fb25e564b65d20738e672e/certifi-2025.6.15.tar.gz", hash = "sha256:d747aa5a8b9bbbb1bb8c22bb13e22bd1f18e9796defa16bab421f7f7a317323b", size = 158753, upload-time = "2025-06-15T02:45:51.329Z" }
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/84/ae/320161bd181fc06471eed047ecce67b693fd7515b16d495d8932db763426/certifi-2025.6.15-py3-none-any.whl", hash = "sha256:2e0c7ce7cb5d8f8634ca55d2ba7e6ec2689a2fd6537d8dec1296a477a4910057", size = 157650, upload-time = "2025-06-15T02:45:49.977Z" },
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.2"
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