ecos-reader 0.3.0__tar.gz → 0.4.0__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.
Files changed (111) hide show
  1. {ecos_reader-0.3.0 → ecos_reader-0.4.0}/.github/workflows/ci.yml +4 -4
  2. {ecos_reader-0.3.0 → ecos_reader-0.4.0}/.github/workflows/codeql.yml +3 -3
  3. {ecos_reader-0.3.0 → ecos_reader-0.4.0}/.github/workflows/docs.yml +3 -3
  4. {ecos_reader-0.3.0 → ecos_reader-0.4.0}/.github/workflows/nightly-e2e.yml +2 -2
  5. {ecos_reader-0.3.0 → ecos_reader-0.4.0}/.github/workflows/publish.yml +6 -6
  6. {ecos_reader-0.3.0 → ecos_reader-0.4.0}/.github/workflows/security.yml +2 -2
  7. {ecos_reader-0.3.0 → ecos_reader-0.4.0}/CHANGELOG.md +17 -0
  8. {ecos_reader-0.3.0 → ecos_reader-0.4.0}/PKG-INFO +1 -1
  9. ecos_reader-0.4.0/docs/user-guide/migration-frequency.md +31 -0
  10. ecos_reader-0.4.0/docs/user-guide/migration-v0.4.0.md +62 -0
  11. {ecos_reader-0.3.0 → ecos_reader-0.4.0}/pyproject.toml +1 -1
  12. {ecos_reader-0.3.0 → ecos_reader-0.4.0}/src/ecos/__init__.py +1 -6
  13. ecos_reader-0.4.0/src/ecos/indicators/_frequency.py +54 -0
  14. {ecos_reader-0.3.0 → ecos_reader-0.4.0}/src/ecos/indicators/growth.py +6 -24
  15. {ecos_reader-0.3.0 → ecos_reader-0.4.0}/src/ecos/indicators/interest_rate.py +2 -6
  16. ecos_reader-0.4.0/tests/indicators/test_frequency.py +92 -0
  17. {ecos_reader-0.3.0 → ecos_reader-0.4.0}/tests/indicators/test_interest_rate.py +1 -1
  18. {ecos_reader-0.3.0 → ecos_reader-0.4.0}/tests/test_e2e_indicators.py +1 -1
  19. {ecos_reader-0.3.0 → ecos_reader-0.4.0}/uv.lock +1 -1
  20. ecos_reader-0.3.0/docs/user-guide/migration-frequency.md +0 -84
  21. ecos_reader-0.3.0/src/ecos/indicators/_frequency.py +0 -105
  22. ecos_reader-0.3.0/tests/indicators/test_frequency.py +0 -152
  23. {ecos_reader-0.3.0 → ecos_reader-0.4.0}/.github/CODEOWNERS +0 -0
  24. {ecos_reader-0.3.0 → ecos_reader-0.4.0}/.github/dependabot.yml +0 -0
  25. {ecos_reader-0.3.0 → ecos_reader-0.4.0}/.gitignore +0 -0
  26. {ecos_reader-0.3.0 → ecos_reader-0.4.0}/.pre-commit-config.yaml +0 -0
  27. {ecos_reader-0.3.0 → ecos_reader-0.4.0}/API_SPEC.md +0 -0
  28. {ecos_reader-0.3.0 → ecos_reader-0.4.0}/CONTRIBUTING.md +0 -0
  29. {ecos_reader-0.3.0 → ecos_reader-0.4.0}/IMPLEMENTATION_STATUS.md +0 -0
  30. {ecos_reader-0.3.0 → ecos_reader-0.4.0}/LICENSE +0 -0
  31. {ecos_reader-0.3.0 → ecos_reader-0.4.0}/README.md +0 -0
  32. {ecos_reader-0.3.0 → ecos_reader-0.4.0}/docs/api-reference/client.md +0 -0
  33. {ecos_reader-0.3.0 → ecos_reader-0.4.0}/docs/api-reference/exceptions.md +0 -0
  34. {ecos_reader-0.3.0 → ecos_reader-0.4.0}/docs/api-reference/indicators.md +0 -0
  35. {ecos_reader-0.3.0 → ecos_reader-0.4.0}/docs/api-reference/overview.md +0 -0
  36. {ecos_reader-0.3.0 → ecos_reader-0.4.0}/docs/api-reference/statistic-item-list.md +0 -0
  37. {ecos_reader-0.3.0 → ecos_reader-0.4.0}/docs/api-reference/statistic-meta.md +0 -0
  38. {ecos_reader-0.3.0 → ecos_reader-0.4.0}/docs/api-reference/statistic-search.md +0 -0
  39. {ecos_reader-0.3.0 → ecos_reader-0.4.0}/docs/api-reference/statistic-table-list.md +0 -0
  40. {ecos_reader-0.3.0 → ecos_reader-0.4.0}/docs/api-reference/statistic-top-100.md +0 -0
  41. {ecos_reader-0.3.0 → ecos_reader-0.4.0}/docs/api-reference/statistic-word.md +0 -0
  42. {ecos_reader-0.3.0 → ecos_reader-0.4.0}/docs/development/contributing.md +0 -0
  43. {ecos_reader-0.3.0 → ecos_reader-0.4.0}/docs/development/indicator-registry.md +0 -0
  44. {ecos_reader-0.3.0 → ecos_reader-0.4.0}/docs/development/partial-coverage-redesign.md +0 -0
  45. {ecos_reader-0.3.0 → ecos_reader-0.4.0}/docs/development/release.md +0 -0
  46. {ecos_reader-0.3.0 → ecos_reader-0.4.0}/docs/examples/basic.md +0 -0
  47. {ecos_reader-0.3.0 → ecos_reader-0.4.0}/docs/examples/dashboard.md +0 -0
  48. {ecos_reader-0.3.0 → ecos_reader-0.4.0}/docs/getting-started/installation.md +0 -0
  49. {ecos_reader-0.3.0 → ecos_reader-0.4.0}/docs/getting-started/quickstart.md +0 -0
  50. {ecos_reader-0.3.0 → ecos_reader-0.4.0}/docs/index.md +0 -0
  51. {ecos_reader-0.3.0 → ecos_reader-0.4.0}/docs/reference/ecos_code_catalog.md +0 -0
  52. {ecos_reader-0.3.0 → ecos_reader-0.4.0}/docs/user-guide/advanced.md +0 -0
  53. {ecos_reader-0.3.0 → ecos_reader-0.4.0}/docs/user-guide/basic-usage.md +0 -0
  54. {ecos_reader-0.3.0 → ecos_reader-0.4.0}/docs/user-guide/financial-markets.md +0 -0
  55. {ecos_reader-0.3.0 → ecos_reader-0.4.0}/docs/user-guide/fiscal.md +0 -0
  56. {ecos_reader-0.3.0 → ecos_reader-0.4.0}/docs/user-guide/growth.md +0 -0
  57. {ecos_reader-0.3.0 → ecos_reader-0.4.0}/docs/user-guide/interest-rates.md +0 -0
  58. {ecos_reader-0.3.0 → ecos_reader-0.4.0}/docs/user-guide/migration-v0.3.0.md +0 -0
  59. {ecos_reader-0.3.0 → ecos_reader-0.4.0}/docs/user-guide/money.md +0 -0
  60. {ecos_reader-0.3.0 → ecos_reader-0.4.0}/docs/user-guide/prices.md +0 -0
  61. {ecos_reader-0.3.0 → ecos_reader-0.4.0}/ecos_all_statistics.csv +0 -0
  62. {ecos_reader-0.3.0 → ecos_reader-0.4.0}/ecos_implementation_status.csv +0 -0
  63. {ecos_reader-0.3.0 → ecos_reader-0.4.0}/examples/basic_usage.py +0 -0
  64. {ecos_reader-0.3.0 → ecos_reader-0.4.0}/examples/macro_dashboard.py +0 -0
  65. {ecos_reader-0.3.0 → ecos_reader-0.4.0}/mkdocs.yml +0 -0
  66. {ecos_reader-0.3.0 → ecos_reader-0.4.0}/public-api-docs/statistic-item-list.md +0 -0
  67. {ecos_reader-0.3.0 → ecos_reader-0.4.0}/public-api-docs/statistic-meta.md +0 -0
  68. {ecos_reader-0.3.0 → ecos_reader-0.4.0}/public-api-docs/statistic-search.md +0 -0
  69. {ecos_reader-0.3.0 → ecos_reader-0.4.0}/public-api-docs/statistic-table-list.md +0 -0
  70. {ecos_reader-0.3.0 → ecos_reader-0.4.0}/public-api-docs/statistic-top-100.md +0 -0
  71. {ecos_reader-0.3.0 → ecos_reader-0.4.0}/public-api-docs/statistic-word.md +0 -0
  72. {ecos_reader-0.3.0 → ecos_reader-0.4.0}/scripts/audit_codes.py +0 -0
  73. {ecos_reader-0.3.0 → ecos_reader-0.4.0}/scripts/gen_indicator_registry_doc.py +0 -0
  74. {ecos_reader-0.3.0 → ecos_reader-0.4.0}/src/ecos/cache.py +0 -0
  75. {ecos_reader-0.3.0 → ecos_reader-0.4.0}/src/ecos/client.py +0 -0
  76. {ecos_reader-0.3.0 → ecos_reader-0.4.0}/src/ecos/config.py +0 -0
  77. {ecos_reader-0.3.0 → ecos_reader-0.4.0}/src/ecos/constants.py +0 -0
  78. {ecos_reader-0.3.0 → ecos_reader-0.4.0}/src/ecos/exceptions.py +0 -0
  79. {ecos_reader-0.3.0 → ecos_reader-0.4.0}/src/ecos/indicators/__init__.py +0 -0
  80. {ecos_reader-0.3.0 → ecos_reader-0.4.0}/src/ecos/indicators/_dates.py +0 -0
  81. {ecos_reader-0.3.0 → ecos_reader-0.4.0}/src/ecos/indicators/_registry.py +0 -0
  82. {ecos_reader-0.3.0 → ecos_reader-0.4.0}/src/ecos/indicators/_subcategory.py +0 -0
  83. {ecos_reader-0.3.0 → ecos_reader-0.4.0}/src/ecos/indicators/bond.py +0 -0
  84. {ecos_reader-0.3.0 → ecos_reader-0.4.0}/src/ecos/indicators/fiscal.py +0 -0
  85. {ecos_reader-0.3.0 → ecos_reader-0.4.0}/src/ecos/indicators/money.py +0 -0
  86. {ecos_reader-0.3.0 → ecos_reader-0.4.0}/src/ecos/indicators/prices.py +0 -0
  87. {ecos_reader-0.3.0 → ecos_reader-0.4.0}/src/ecos/indicators/stock.py +0 -0
  88. {ecos_reader-0.3.0 → ecos_reader-0.4.0}/src/ecos/logging.py +0 -0
  89. {ecos_reader-0.3.0 → ecos_reader-0.4.0}/src/ecos/metrics.py +0 -0
  90. {ecos_reader-0.3.0 → ecos_reader-0.4.0}/src/ecos/parser.py +0 -0
  91. {ecos_reader-0.3.0 → ecos_reader-0.4.0}/src/ecos/py.typed +0 -0
  92. {ecos_reader-0.3.0 → ecos_reader-0.4.0}/src/ecos/types.py +0 -0
  93. {ecos_reader-0.3.0 → ecos_reader-0.4.0}/tests/__init__.py +0 -0
  94. {ecos_reader-0.3.0 → ecos_reader-0.4.0}/tests/conftest.py +0 -0
  95. {ecos_reader-0.3.0 → ecos_reader-0.4.0}/tests/indicators/__init__.py +0 -0
  96. {ecos_reader-0.3.0 → ecos_reader-0.4.0}/tests/indicators/test_bond.py +0 -0
  97. {ecos_reader-0.3.0 → ecos_reader-0.4.0}/tests/indicators/test_dates.py +0 -0
  98. {ecos_reader-0.3.0 → ecos_reader-0.4.0}/tests/indicators/test_fiscal.py +0 -0
  99. {ecos_reader-0.3.0 → ecos_reader-0.4.0}/tests/indicators/test_growth.py +0 -0
  100. {ecos_reader-0.3.0 → ecos_reader-0.4.0}/tests/indicators/test_money.py +0 -0
  101. {ecos_reader-0.3.0 → ecos_reader-0.4.0}/tests/indicators/test_prices.py +0 -0
  102. {ecos_reader-0.3.0 → ecos_reader-0.4.0}/tests/indicators/test_registry.py +0 -0
  103. {ecos_reader-0.3.0 → ecos_reader-0.4.0}/tests/indicators/test_stock.py +0 -0
  104. {ecos_reader-0.3.0 → ecos_reader-0.4.0}/tests/indicators/test_subcategory.py +0 -0
  105. {ecos_reader-0.3.0 → ecos_reader-0.4.0}/tests/test_cache.py +0 -0
  106. {ecos_reader-0.3.0 → ecos_reader-0.4.0}/tests/test_client.py +0 -0
  107. {ecos_reader-0.3.0 → ecos_reader-0.4.0}/tests/test_codes_live.py +0 -0
  108. {ecos_reader-0.3.0 → ecos_reader-0.4.0}/tests/test_config.py +0 -0
  109. {ecos_reader-0.3.0 → ecos_reader-0.4.0}/tests/test_e2e.py +0 -0
  110. {ecos_reader-0.3.0 → ecos_reader-0.4.0}/tests/test_exceptions.py +0 -0
  111. {ecos_reader-0.3.0 → ecos_reader-0.4.0}/tests/test_parser.py +0 -0
@@ -27,10 +27,10 @@ jobs:
27
27
  name: Lint & type-check
28
28
  runs-on: ubuntu-latest
29
29
  steps:
30
- - uses: actions/checkout@v4
30
+ - uses: actions/checkout@v6
31
31
 
32
32
  - name: Install uv
33
- uses: astral-sh/setup-uv@v3
33
+ uses: astral-sh/setup-uv@v8.1.0
34
34
  with:
35
35
  enable-cache: true
36
36
 
@@ -58,10 +58,10 @@ jobs:
58
58
  matrix:
59
59
  python-version: ["3.10", "3.11", "3.12"]
60
60
  steps:
61
- - uses: actions/checkout@v4
61
+ - uses: actions/checkout@v6
62
62
 
63
63
  - name: Install uv
64
- uses: astral-sh/setup-uv@v3
64
+ uses: astral-sh/setup-uv@v8.1.0
65
65
  with:
66
66
  enable-cache: true
67
67
 
@@ -24,15 +24,15 @@ jobs:
24
24
  security-events: write
25
25
  contents: read
26
26
  steps:
27
- - uses: actions/checkout@v4
27
+ - uses: actions/checkout@v6
28
28
 
29
29
  - name: Initialize CodeQL
30
- uses: github/codeql-action/init@v3
30
+ uses: github/codeql-action/init@v4
31
31
  with:
32
32
  languages: python
33
33
  queries: security-extended
34
34
 
35
35
  - name: Perform CodeQL Analysis
36
- uses: github/codeql-action/analyze@v3
36
+ uses: github/codeql-action/analyze@v4
37
37
  with:
38
38
  category: "/language:python"
@@ -15,10 +15,10 @@ jobs:
15
15
  deploy:
16
16
  runs-on: ubuntu-latest
17
17
  steps:
18
- - uses: actions/checkout@v4
18
+ - uses: actions/checkout@v6
19
19
 
20
20
  - name: Install uv
21
- uses: astral-sh/setup-uv@v3
21
+ uses: astral-sh/setup-uv@v8.1.0
22
22
  with:
23
23
  enable-cache: true
24
24
 
@@ -32,7 +32,7 @@ jobs:
32
32
 
33
33
  - name: Deploy to GitHub Pages
34
34
  if: github.event_name == 'push' && github.ref == 'refs/heads/main'
35
- uses: peaceiris/actions-gh-pages@v3
35
+ uses: peaceiris/actions-gh-pages@v4
36
36
  with:
37
37
  github_token: ${{ secrets.GITHUB_TOKEN }}
38
38
  publish_dir: ./site
@@ -24,10 +24,10 @@ jobs:
24
24
  # fork에는 secret이 없어 의미가 없으므로 upstream 레포에서만 실행
25
25
  if: github.repository == 'choo121600/ecos-reader'
26
26
  steps:
27
- - uses: actions/checkout@v4
27
+ - uses: actions/checkout@v6
28
28
 
29
29
  - name: Install uv
30
- uses: astral-sh/setup-uv@v3
30
+ uses: astral-sh/setup-uv@v8.1.0
31
31
  with:
32
32
  enable-cache: true
33
33
 
@@ -27,10 +27,10 @@ jobs:
27
27
  runs-on: ubuntu-latest
28
28
 
29
29
  steps:
30
- - uses: actions/checkout@v4
30
+ - uses: actions/checkout@v6
31
31
 
32
32
  - name: Set up Python
33
- uses: actions/setup-python@v5
33
+ uses: actions/setup-python@v6
34
34
  with:
35
35
  python-version: '3.10'
36
36
 
@@ -43,7 +43,7 @@ jobs:
43
43
  run: python -m build
44
44
 
45
45
  - name: Store the distribution packages
46
- uses: actions/upload-artifact@v4
46
+ uses: actions/upload-artifact@v7
47
47
  with:
48
48
  name: python-package-distributions
49
49
  path: dist/
@@ -61,7 +61,7 @@ jobs:
61
61
 
62
62
  steps:
63
63
  - name: Download all the dists
64
- uses: actions/download-artifact@v4
64
+ uses: actions/download-artifact@v8
65
65
  with:
66
66
  name: python-package-distributions
67
67
  path: dist/
@@ -78,10 +78,10 @@ jobs:
78
78
  contents: write # IMPORTANT: mandatory for creating releases
79
79
 
80
80
  steps:
81
- - uses: actions/checkout@v4
81
+ - uses: actions/checkout@v6
82
82
 
83
83
  - name: Download all the dists
84
- uses: actions/download-artifact@v4
84
+ uses: actions/download-artifact@v8
85
85
  with:
86
86
  name: python-package-distributions
87
87
  path: dist/
@@ -20,10 +20,10 @@ jobs:
20
20
  name: pip-audit
21
21
  runs-on: ubuntu-latest
22
22
  steps:
23
- - uses: actions/checkout@v4
23
+ - uses: actions/checkout@v6
24
24
 
25
25
  - name: Install uv
26
- uses: astral-sh/setup-uv@v3
26
+ uses: astral-sh/setup-uv@v8.1.0
27
27
  with:
28
28
  enable-cache: true
29
29
 
@@ -5,6 +5,22 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [0.4.0] - 2026-05-31
9
+
10
+ > Epic #57(Deprecation 정리)의 **BREAKING** 릴리스. v0.2.2(#20)에서
11
+ > `EcosDeprecationWarning` 과 함께 deprecated 처리됐던 레거시 frequency
12
+ > 단일 문자 표기를 제거합니다. 마이그레이션: 사용자 가이드 > v0.4.0 마이그레이션.
13
+
14
+ ### Removed (BREAKING)
15
+ - 레거시 `frequency` 단일 문자 표기(`"D"`/`"M"`/`"Q"`/`"A"`) 제거. 이제 정식
16
+ 어휘(`"daily"`/`"monthly"`/`"quarterly"`/`"annual"`)만 허용하며, 정식이 아닌
17
+ 값은 경고 없이 즉시 `ValueError` 를 발생시킵니다. (#65)
18
+ - `EcosDeprecationWarning` 클래스 및 공개 export 제거. frequency 단일 문자
19
+ 표기 전용 경고였으며, 해당 표기 제거와 함께 더 이상 노출되지 않습니다. (#65)
20
+
21
+ ### Added
22
+ - v0.4.0 마이그레이션 가이드(사용자 가이드). (#66)
23
+
8
24
  ## [0.3.0] - 2026-05-31
9
25
 
10
26
  > Epic #56(Partial-coverage 재설계)의 **BREAKING** 릴리스. 함수명이 전체 시리즈를
@@ -320,6 +336,7 @@ v0.1.6 라이브 e2e 검증에서 드러난 follow-up(#2 Reliability epic)을
320
336
  - 기본 사용법 (`examples/basic_usage.py`)
321
337
  - 거시경제 대시보드 (`examples/macro_dashboard.py`)
322
338
 
339
+ [0.4.0]: https://github.com/choo121600/ecos-reader/compare/v0.3.0...v0.4.0
323
340
  [0.3.0]: https://github.com/choo121600/ecos-reader/compare/v0.2.2...v0.3.0
324
341
  [0.1.2]: https://github.com/choo121600/ecos-reader/compare/v0.1.1...v0.1.2
325
342
  [0.1.1]: https://github.com/choo121600/ecos-reader/compare/v0.1.0...v0.1.1
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ecos-reader
3
- Version: 0.3.0
3
+ Version: 0.4.0
4
4
  Summary: 한국은행 ECOS Open API Python 클라이언트
5
5
  Project-URL: Homepage, https://github.com/choo121600/ecos-reader
6
6
  Project-URL: Documentation, https://choo121600.github.io/ecos-reader/
@@ -0,0 +1,31 @@
1
+ # frequency 표기 마이그레이션 (#20, #57)
2
+
3
+ 이 문서는 `frequency` 인자 표기 변경(레거시 단일 문자 → 정식 풀네임)에 대한 안내입니다.
4
+ v0.4.0(#57)부터 레거시 단일 문자 표기는 **제거**되어 더 이상 허용되지 않습니다.
5
+
6
+ ## 한눈에 보기
7
+
8
+ | 카테고리 | 함수 | 레거시(제거됨) | 정식(필수) |
9
+ |---|---|---|---|
10
+ | 성장 | `get_gdp`, `get_gdp_deflator` 등 | `Q`, `A` | `quarterly`, `annual` |
11
+ | 금리 | `get_base_rate` | `D`, `M` | `daily`, `monthly` |
12
+ | 주식 | `get_stock_index` | (없음) | `daily`, `monthly` |
13
+
14
+ ## 권장 변경
15
+
16
+ ```python
17
+ # Before (v0.3.x 이하, 이제 ValueError)
18
+ df = ecos.get_gdp(frequency="Q")
19
+
20
+ # After (정식)
21
+ df = ecos.get_gdp(frequency="quarterly")
22
+ ```
23
+
24
+ ## 동작/타임라인
25
+
26
+ - v0.2.2: 정식 어휘 도입. 레거시 단일 문자는 `EcosDeprecationWarning` 과 함께 계속 동작.
27
+ - **v0.4.0: 레거시 단일 문자 제거.** 이제 정식 어휘만 허용하며, 정식이 아닌
28
+ 값은 경고 없이 즉시 `ValueError` 입니다. frequency 전용 경고였던
29
+ `EcosDeprecationWarning` 도 함께 제거되었습니다.
30
+
31
+ v0.4.0 변경 상세는 [v0.4.0 마이그레이션](migration-v0.4.0.md) 을 참고하세요.
@@ -0,0 +1,62 @@
1
+ # v0.4.0 마이그레이션 가이드
2
+
3
+ v0.4.0은 deprecation cycle이 만료된 항목을 제거하는 **BREAKING** 릴리스입니다.
4
+ v0.2.2(#20)에서 `EcosDeprecationWarning` 과 함께 deprecated 처리된 레거시
5
+ frequency 단일 문자 표기가 제거되었습니다.
6
+
7
+ ## 무엇이 바뀌었나
8
+
9
+ - 레거시 frequency 단일 문자 표기(`"D"` / `"M"` / `"Q"` / `"A"`)가 **제거**되었습니다.
10
+ - 이제 정식(canonical) 어휘만 허용합니다.
11
+
12
+ | 레거시 (제거됨) | 정식 어휘 |
13
+ | :-------------- | :---------- |
14
+ | `"D"` | `"daily"` |
15
+ | `"M"` | `"monthly"` |
16
+ | `"Q"` | `"quarterly"` |
17
+ | `"A"` | `"annual"` |
18
+
19
+ - 정식이 아닌 값은 경고 없이 **즉시 `ValueError`** 를 발생시킵니다.
20
+ (이전에는 레거시 표기를 `EcosDeprecationWarning` 과 함께 통과시켰습니다.)
21
+ - frequency 전용 경고였던 `EcosDeprecationWarning` 클래스가 제거되어
22
+ `ecos` 패키지에서 더 이상 export되지 않습니다.
23
+
24
+ ## 영향을 받는 함수
25
+
26
+ frequency 인자를 받는 지표 함수들입니다.
27
+
28
+ - `get_gdp` 등 성장 지표: `"quarterly"` / `"annual"`
29
+ - `get_base_rate` 등 금리 지표: `"daily"` / `"monthly"`
30
+ - `get_stock_index` 등 주식 지표: `"daily"` / `"monthly"`
31
+
32
+ ## 코드 변경 방법
33
+
34
+ 레거시 단일 문자를 정식 어휘로 교체하세요.
35
+
36
+ ```python
37
+ import ecos
38
+
39
+ # 이전 (v0.3.x 이하) — deprecated, v0.4.0에서 제거됨 (이제 ValueError)
40
+ df = ecos.get_gdp(frequency="Q")
41
+ df = ecos.get_base_rate(frequency="D")
42
+
43
+ # 이후 (v0.4.0+)
44
+ df = ecos.get_gdp(frequency="quarterly")
45
+ df = ecos.get_base_rate(frequency="daily")
46
+ ```
47
+
48
+ `EcosDeprecationWarning` 을 직접 참조하던 코드가 있다면 제거하세요.
49
+
50
+ ```python
51
+ # 이전 — 더 이상 동작하지 않음 (ImportError)
52
+ import warnings
53
+ from ecos import EcosDeprecationWarning
54
+ warnings.simplefilter("ignore", EcosDeprecationWarning)
55
+
56
+ # 이후 — 해당 경고가 제거되었으므로 이 코드는 불필요합니다.
57
+ ```
58
+
59
+ ## 참고
60
+
61
+ - `_registry.py` 의 `DateFormat = Literal["D", "M", "Q", "A"]` 는 ECOS API의
62
+ 내부 period 코드로, frequency 어휘와 무관하며 변경되지 않았습니다.
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "ecos-reader"
7
- version = "0.3.0"
7
+ version = "0.4.0"
8
8
  description = "한국은행 ECOS Open API Python 클라이언트"
9
9
  readme = "README.md"
10
10
  license = "MIT"
@@ -20,7 +20,7 @@ Examples
20
20
 
21
21
  from __future__ import annotations
22
22
 
23
- __version__ = "0.3.0"
23
+ __version__ = "0.4.0"
24
24
  __author__ = "yeonguk"
25
25
 
26
26
  # Config API
@@ -86,9 +86,6 @@ from .indicators import (
86
86
  list_indicators,
87
87
  )
88
88
 
89
- # Warnings
90
- from .indicators._frequency import EcosDeprecationWarning
91
-
92
89
  # Logging API
93
90
  from .logging import setup_logging
94
91
 
@@ -120,8 +117,6 @@ __all__ = [
120
117
  "EcosRateLimitError",
121
118
  "EcosServerError",
122
119
  "EcosValidationError",
123
- # Warnings
124
- "EcosDeprecationWarning",
125
120
  # 재정 지표
126
121
  "get_fiscal_balance",
127
122
  # 주식시장 지표
@@ -0,0 +1,54 @@
1
+ """
2
+ frequency 어휘 통일 (#20, #57).
3
+
4
+ 과거에는 카테고리마다 ``frequency`` 값 표기가 달랐고, 레거시 단일 문자
5
+ 표기(``D``/``M``/``Q``/``A``)를 :class:`EcosDeprecationWarning` 과 함께
6
+ 한시적으로 허용했다.
7
+
8
+ v0.4.0(#57)부터 레거시 표기는 **제거**되었으며, 정식(canonical) 풀네임
9
+ 어휘만 허용한다::
10
+
11
+ daily | monthly | quarterly | annual
12
+
13
+ 정식이 아닌 값은 경고 없이 즉시 :class:`ValueError` 로 처리한다.
14
+ """
15
+
16
+ from __future__ import annotations
17
+
18
+
19
+ def normalize_frequency(
20
+ value: str,
21
+ *,
22
+ allowed: tuple[str, ...],
23
+ func_name: str,
24
+ ) -> str:
25
+ """frequency 값을 검증한다.
26
+
27
+ Parameters
28
+ ----------
29
+ value : str
30
+ 호출자가 전달한 frequency 값
31
+ (정식 어휘 ``daily``/``monthly``/``quarterly``/``annual``).
32
+ allowed : tuple of str
33
+ 해당 지표가 지원하는 정식 frequency 값의 튜플
34
+ (예: ``("quarterly", "annual")``).
35
+ func_name : str
36
+ 에러 메시지에 쓰이는 공개 함수명(예: ``"get_gdp"``).
37
+
38
+ Returns
39
+ -------
40
+ str
41
+ 검증된 frequency 값.
42
+
43
+ Raises
44
+ ------
45
+ ValueError
46
+ ``value`` 가 ``allowed`` 에 없을 때. 레거시 단일 문자 표기
47
+ (``D``/``M``/``Q``/``A``)는 v0.4.0에서 제거되었으므로 동일하게
48
+ ``ValueError`` 로 처리된다.
49
+ """
50
+ if value not in allowed:
51
+ allowed_str = " 또는 ".join(repr(a) for a in allowed)
52
+ raise ValueError(f"{func_name}(): frequency는 {allowed_str} 중 하나여야 합니다.")
53
+
54
+ return value
@@ -34,7 +34,7 @@ if TYPE_CHECKING:
34
34
 
35
35
 
36
36
  def get_gdp(
37
- frequency: Literal["quarterly", "annual", "Q", "A"] = "quarterly",
37
+ frequency: Literal["quarterly", "annual"] = "quarterly",
38
38
  basis: Literal["real", "nominal"] = "real",
39
39
  start_date: str | None = None,
40
40
  end_date: str | None = None,
@@ -48,9 +48,6 @@ def get_gdp(
48
48
  조회 주기
49
49
  - 'quarterly': 분기 (기본값)
50
50
  - 'annual': 연간
51
-
52
- 레거시 'Q'/'A'도 당분간 허용되나 EcosDeprecationWarning과 함께
53
- deprecated이며 v0.4.0에서 제거됩니다.
54
51
  basis : str
55
52
  GDP 기준
56
53
  - 'real': 실질 GDP (기본값)
@@ -114,7 +111,7 @@ def get_gdp(
114
111
 
115
112
 
116
113
  def get_gdp_deflator(
117
- frequency: Literal["quarterly", "annual", "Q", "A"] = "quarterly",
114
+ frequency: Literal["quarterly", "annual"] = "quarterly",
118
115
  start_date: str | None = None,
119
116
  end_date: str | None = None,
120
117
  ) -> pd.DataFrame:
@@ -130,9 +127,6 @@ def get_gdp_deflator(
130
127
  조회 주기
131
128
  - 'quarterly': 분기 (기본값)
132
129
  - 'annual': 연간
133
-
134
- 레거시 'Q'/'A'도 당분간 허용되나 EcosDeprecationWarning과 함께
135
- deprecated이며 v0.4.0에서 제거됩니다.
136
130
  start_date : str, optional
137
131
  조회 시작일
138
132
  end_date : str, optional
@@ -188,7 +182,7 @@ def get_gdp_deflator(
188
182
 
189
183
 
190
184
  def get_gdp_growth_rate(
191
- frequency: Literal["quarterly", "annual", "Q", "A"] = "quarterly",
185
+ frequency: Literal["quarterly", "annual"] = "quarterly",
192
186
  start_date: str | None = None,
193
187
  end_date: str | None = None,
194
188
  ) -> pd.DataFrame:
@@ -203,9 +197,6 @@ def get_gdp_growth_rate(
203
197
  조회 주기
204
198
  - 'quarterly': 분기 (기본값)
205
199
  - 'annual': 연간
206
-
207
- 레거시 'Q'/'A'도 당분간 허용되나 EcosDeprecationWarning과 함께
208
- deprecated이며 v0.4.0에서 제거됩니다.
209
200
  start_date : str, optional
210
201
  조회 시작일
211
202
  - 분기: YYYYQN 형식 (예: 2020Q1)
@@ -271,7 +262,7 @@ def get_gdp_growth_rate(
271
262
  def get_gdp_by_industry(
272
263
  basis: Literal["real", "nominal"] = "real",
273
264
  seasonal_adj: bool = True,
274
- frequency: Literal["quarterly", "annual", "Q", "A"] = "quarterly",
265
+ frequency: Literal["quarterly", "annual"] = "quarterly",
275
266
  sub_category: str | None = None,
276
267
  start_date: str | None = None,
277
268
  end_date: str | None = None,
@@ -295,9 +286,6 @@ def get_gdp_by_industry(
295
286
  조회 주기
296
287
  - 'quarterly': 분기 (기본값)
297
288
  - 'annual': 연간
298
-
299
- 레거시 'Q'/'A'도 당분간 허용되나 EcosDeprecationWarning과 함께
300
- deprecated이며 v0.4.0에서 제거됩니다.
301
289
  sub_category : str, optional
302
290
  세부 산업(항목명 또는 item_code1). 지정 시 해당 산업 단일 시계열만
303
291
  반환합니다. 미지정 시 전체 산업을 long-format으로 반환합니다.
@@ -395,7 +383,7 @@ def get_gdp_by_industry(
395
383
 
396
384
  def get_gdp_by_expenditure(
397
385
  basis: Literal["real", "nominal"] = "real",
398
- frequency: Literal["quarterly", "annual", "Q", "A"] = "quarterly",
386
+ frequency: Literal["quarterly", "annual"] = "quarterly",
399
387
  sub_category: str | None = None,
400
388
  start_date: str | None = None,
401
389
  end_date: str | None = None,
@@ -417,9 +405,6 @@ def get_gdp_by_expenditure(
417
405
  조회 주기
418
406
  - 'quarterly': 분기 (기본값)
419
407
  - 'annual': 연간
420
-
421
- 레거시 'Q'/'A'도 당분간 허용되나 EcosDeprecationWarning과 함께
422
- deprecated이며 v0.4.0에서 제거됩니다.
423
408
  sub_category : str, optional
424
409
  세부 지출항목(항목명 또는 item_code1). 지정 시 해당 항목 단일 시계열만
425
410
  반환합니다. 미지정 시 전체 지출항목을 long-format으로 반환합니다.
@@ -512,7 +497,7 @@ def get_gdp_by_expenditure(
512
497
 
513
498
 
514
499
  def get_gdp_deflator_by_industry(
515
- frequency: Literal["quarterly", "annual", "Q", "A"] = "quarterly",
500
+ frequency: Literal["quarterly", "annual"] = "quarterly",
516
501
  sub_category: str | None = None,
517
502
  start_date: str | None = None,
518
503
  end_date: str | None = None,
@@ -530,9 +515,6 @@ def get_gdp_deflator_by_industry(
530
515
  조회 주기
531
516
  - 'quarterly': 분기 (기본값)
532
517
  - 'annual': 연간
533
-
534
- 레거시 'Q'/'A'도 당분간 허용되나 EcosDeprecationWarning과 함께
535
- deprecated이며 v0.4.0에서 제거됩니다.
536
518
  sub_category : str, optional
537
519
  세부 산업(항목명 또는 item_code1). 지정 시 해당 산업 단일 시계열만
538
520
  반환합니다. 미지정 시 전체 산업을 long-format으로 반환합니다.
@@ -32,7 +32,7 @@ from ._registry import get_indicator
32
32
  def get_base_rate(
33
33
  start_date: str | None = None,
34
34
  end_date: str | None = None,
35
- frequency: Literal["daily", "monthly", "D", "M"] = "monthly",
35
+ frequency: Literal["daily", "monthly"] = "monthly",
36
36
  ) -> pd.DataFrame:
37
37
  """
38
38
  한국은행 기준금리를 조회합니다.
@@ -50,10 +50,6 @@ def get_base_rate(
50
50
  - 'daily': 일별 (날짜 YYYYMMDD). 기준금리는 변경일에만 갱신되어
51
51
  결과가 sparse 합니다 (변경이 없는 날은 행이 없음).
52
52
 
53
- 레거시 단일 문자(``'M'``/``'D'``)도 당분간 허용되나
54
- :class:`~ecos.EcosDeprecationWarning` 과 함께 deprecated이며
55
- v0.4.0에서 제거됩니다.
56
-
57
53
  Returns
58
54
  -------
59
55
  pd.DataFrame
@@ -74,7 +70,7 @@ def get_base_rate(
74
70
 
75
71
  >>> # 일별 (변경일 단위) 조회
76
72
  >>> df = ecos.get_base_rate(
77
- ... start_date="20200101", end_date="20231231", frequency="D"
73
+ ... start_date="20200101", end_date="20231231", frequency="daily"
78
74
  ... )
79
75
  """
80
76
  frequency = normalize_frequency( # type: ignore[assignment]
@@ -0,0 +1,92 @@
1
+ """frequency 정규화 동작 검증 (#20, #57).
2
+
3
+ 정식 어휘(daily/monthly/quarterly/annual)만 허용한다. 레거시 단일 문자
4
+ (D/M/Q/A)는 v0.4.0(#57)에서 제거되어 즉시 ValueError로 처리된다.
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ import warnings
10
+
11
+ import pytest
12
+
13
+ from ecos.indicators._frequency import normalize_frequency
14
+
15
+
16
+ class TestNormalizeFrequencyCanonical:
17
+ """정식 어휘는 그대로 통과한다."""
18
+
19
+ def test_canonical_passthrough(self):
20
+ for value in ("daily", "monthly", "quarterly", "annual"):
21
+ assert (
22
+ normalize_frequency(
23
+ value,
24
+ allowed=("daily", "monthly", "quarterly", "annual"),
25
+ func_name="test",
26
+ )
27
+ == value
28
+ )
29
+
30
+ def test_canonical_no_warning(self):
31
+ with warnings.catch_warnings():
32
+ warnings.simplefilter("error")
33
+ result = normalize_frequency("monthly", allowed=("monthly",), func_name="test")
34
+ assert result == "monthly"
35
+
36
+
37
+ class TestNormalizeFrequencyLegacyRemoved:
38
+ """레거시 단일 문자는 제거되어 즉시 ValueError로 처리된다."""
39
+
40
+ def test_legacy_aliases_raise(self):
41
+ for legacy in ("D", "M", "Q", "A"):
42
+ with pytest.raises(ValueError, match="frequency"):
43
+ normalize_frequency(
44
+ legacy,
45
+ allowed=("daily", "monthly", "quarterly", "annual"),
46
+ func_name="test",
47
+ )
48
+
49
+ def test_legacy_raises_without_warning(self):
50
+ """레거시 표기는 경고 없이 곧바로 ValueError."""
51
+ with warnings.catch_warnings():
52
+ warnings.simplefilter("error")
53
+ with pytest.raises(ValueError, match="frequency"):
54
+ normalize_frequency("Q", allowed=("quarterly", "annual"), func_name="get_gdp")
55
+
56
+ def test_invalid_raises_valueerror(self):
57
+ with pytest.raises(ValueError, match="frequency"):
58
+ normalize_frequency("W", allowed=("daily", "monthly"), func_name="test")
59
+
60
+ def test_canonical_outside_allowed_raises(self):
61
+ """정식 어휘라도 allowed에 없으면 ValueError."""
62
+ with pytest.raises(ValueError, match="frequency"):
63
+ normalize_frequency("daily", allowed=("quarterly", "annual"), func_name="test")
64
+
65
+ def test_error_message_includes_func_name(self):
66
+ with pytest.raises(ValueError, match="get_gdp"):
67
+ normalize_frequency("Q", allowed=("quarterly", "annual"), func_name="get_gdp")
68
+
69
+
70
+ class TestFrequencyWiringPerFunction:
71
+ """per-function wiring: 레거시 표기는 ValueError로 거부된다."""
72
+
73
+ def test_get_gdp_legacy_quarterly_raises(self):
74
+ """get_gdp(frequency='Q')는 ValueError."""
75
+ from ecos import get_gdp
76
+
77
+ with pytest.raises(ValueError, match="frequency"):
78
+ get_gdp(frequency="Q", start_date="2024Q1", end_date="2024Q1")
79
+
80
+ def test_get_base_rate_legacy_daily_raises(self):
81
+ """get_base_rate(frequency='D')는 ValueError."""
82
+ from ecos import get_base_rate
83
+
84
+ with pytest.raises(ValueError, match="frequency"):
85
+ get_base_rate(frequency="D", start_date="20240101", end_date="20241231")
86
+
87
+ def test_get_stock_index_legacy_daily_raises(self):
88
+ """get_stock_index(frequency='D')는 ValueError."""
89
+ from ecos import get_stock_index
90
+
91
+ with pytest.raises(ValueError, match="frequency"):
92
+ get_stock_index(frequency="D")
@@ -57,7 +57,7 @@ class TestGetBaseRate:
57
57
 
58
58
  @responses.activate
59
59
  def test_get_base_rate_daily_frequency(self):
60
- """일별(frequency='D') 조회 — 722Y001 은 일별 원천."""
60
+ """일별(frequency='daily') 조회 — 722Y001 은 일별 원천."""
61
61
  mock_response = {
62
62
  "StatisticSearch": {
63
63
  "row": [
@@ -772,7 +772,7 @@ class TestE2ERegressionV016:
772
772
  # ---- GDP 연간 fallback (#28) ----
773
773
 
774
774
  def test_gdp_growth_rate_annual_fallback(self):
775
- """frequency='A' 계절조정(분기 전용) 대신 원계열 200Y106으로 fallback해야 함."""
775
+ """frequency='annual' 계절조정(분기 전용) 대신 원계열 200Y106으로 fallback해야 함."""
776
776
  df = ecos.get_gdp_growth_rate(frequency="annual", start_date="2020", end_date="2023")
777
777
 
778
778
  assert not df.empty
@@ -272,7 +272,7 @@ wheels = [
272
272
 
273
273
  [[package]]
274
274
  name = "ecos-reader"
275
- version = "0.3.0"
275
+ version = "0.4.0"
276
276
  source = { editable = "." }
277
277
  dependencies = [
278
278
  { name = "pandas" },