DefStream 0.1.13__tar.gz → 0.1.14__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.
- defstream-0.1.13/.github/ISSUE_TEMPLATE/feature_request.yml → defstream-0.1.14/.github/ISSUE_TEMPLATE/01.feature.yml +5 -2
- defstream-0.1.13/.github/ISSUE_TEMPLATE/bug_report.yml → defstream-0.1.14/.github/ISSUE_TEMPLATE/02.bug.yml +4 -1
- defstream-0.1.14/.github/ISSUE_TEMPLATE/03.fix.yml +57 -0
- defstream-0.1.14/.github/ISSUE_TEMPLATE/04.task.yml +40 -0
- {defstream-0.1.13 → defstream-0.1.14}/.github/PULL_REQUEST_TEMPLATE.md +1 -1
- {defstream-0.1.13 → defstream-0.1.14}/.github/workflows/ci.yml +30 -2
- {defstream-0.1.13 → defstream-0.1.14}/DefStream.egg-info/PKG-INFO +6 -6
- {defstream-0.1.13 → defstream-0.1.14}/DefStream.egg-info/SOURCES.txt +36 -27
- {defstream-0.1.13 → defstream-0.1.14}/PKG-INFO +6 -6
- {defstream-0.1.13 → defstream-0.1.14}/README.en.md +59 -8
- {defstream-0.1.13 → defstream-0.1.14}/README.md +5 -5
- {defstream-0.1.13 → defstream-0.1.14}/issues/feature/8/IMPLEMENTS.md +5 -5
- {defstream-0.1.13 → defstream-0.1.14}/issues/feature/8/README.md +2 -2
- {defstream-0.1.13 → defstream-0.1.14}/issues/fix/10/IMPLEMENTS.md +3 -3
- {defstream-0.1.13 → defstream-0.1.14}/issues/fix/13/README.md +1 -1
- defstream-0.1.14/issues/fix/21/IMPLEMENTS.md +38 -0
- defstream-0.1.14/issues/fix/21/ISSUE.md +17 -0
- defstream-0.1.14/issues/fix/21/README.md +44 -0
- defstream-0.1.14/issues/fix/21/REQUIREMENTS.md +68 -0
- {defstream-0.1.13 → defstream-0.1.14}/issues/fix/3/IMPLEMENTS.md +1 -1
- {defstream-0.1.13 → defstream-0.1.14}/issues/fix/6/IMPLEMENTS.md +2 -2
- {defstream-0.1.13 → defstream-0.1.14}/issues/fix/6/README.md +1 -1
- {defstream-0.1.13 → defstream-0.1.14}/issues/fix/6/REQUIREMENTS.md +3 -3
- defstream-0.1.14/issues/task/18/IMPLEMENTS.md +96 -0
- defstream-0.1.14/issues/task/18/README.md +37 -0
- defstream-0.1.14/issues/task/18/REQUIREMENTS.md +59 -0
- {defstream-0.1.13 → defstream-0.1.14}/src/Validator/Patterns/Common.py +2 -3
- {defstream-0.1.13 → defstream-0.1.14}/src/Validator/Patterns/__init__.py +2 -2
- {defstream-0.1.13/test → defstream-0.1.14/tests}/test_logging.py +2 -2
- {defstream-0.1.13/test → defstream-0.1.14/tests}/test_release_workflow.py +62 -0
- defstream-0.1.14/tests/test_validator_patterns.py +48 -0
- defstream-0.1.13/.github/PULL_REQUEST_TEMPLATE/hotfix.md +0 -34
- {defstream-0.1.13 → defstream-0.1.14}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {defstream-0.1.13 → defstream-0.1.14}/.gitignore +0 -0
- {defstream-0.1.13 → defstream-0.1.14}/DefStream.egg-info/dependency_links.txt +0 -0
- {defstream-0.1.13 → defstream-0.1.14}/DefStream.egg-info/requires.txt +0 -0
- {defstream-0.1.13 → defstream-0.1.14}/DefStream.egg-info/top_level.txt +0 -0
- {defstream-0.1.13 → defstream-0.1.14}/LICENSE +0 -0
- {defstream-0.1.13 → defstream-0.1.14}/issues/bug/16/IMPLEMENTS.md +0 -0
- {defstream-0.1.13 → defstream-0.1.14}/issues/bug/16/ISSUE.md +0 -0
- {defstream-0.1.13 → defstream-0.1.14}/issues/bug/16/README.md +0 -0
- {defstream-0.1.13 → defstream-0.1.14}/issues/bug/16/REQUIREMENTS.md +0 -0
- {defstream-0.1.13 → defstream-0.1.14}/issues/feature/1/IMPLEMENTS.md +0 -0
- {defstream-0.1.13 → defstream-0.1.14}/issues/feature/1/README.md +0 -0
- {defstream-0.1.13 → defstream-0.1.14}/issues/feature/1/REQUIREMENTS.md +0 -0
- {defstream-0.1.13 → defstream-0.1.14}/issues/feature/1/TASK.md +0 -0
- {defstream-0.1.13 → defstream-0.1.14}/issues/feature/1/ci.refs.json +0 -0
- {defstream-0.1.13 → defstream-0.1.14}/issues/feature/8/REQUIREMENTS.md +0 -0
- {defstream-0.1.13 → defstream-0.1.14}/issues/feature/8/ci.refs.json +0 -0
- {defstream-0.1.13 → defstream-0.1.14}/issues/fix/10/README.md +0 -0
- {defstream-0.1.13 → defstream-0.1.14}/issues/fix/10/REQUIREMENTS.md +0 -0
- {defstream-0.1.13 → defstream-0.1.14}/issues/fix/3/README.md +0 -0
- {defstream-0.1.13 → defstream-0.1.14}/issues/fix/3/REQUIREMENTS.md +0 -0
- {defstream-0.1.13 → defstream-0.1.14}/issues/fix/3/ci.refs.json +0 -0
- {defstream-0.1.13/sample → defstream-0.1.14/samples}/Broker/Sample.py +0 -0
- {defstream-0.1.13/sample → defstream-0.1.14/samples}/Worker/RabbitMQ/Client.py +0 -0
- {defstream-0.1.13/sample → defstream-0.1.14/samples}/Worker/RabbitMQ/Tasks.py +0 -0
- {defstream-0.1.13/sample → defstream-0.1.14/samples}/Worker/RabbitMQ/Worker.py +0 -0
- {defstream-0.1.13/sample → defstream-0.1.14/samples}/Worker/Redis/Sample.py +0 -0
- {defstream-0.1.13/sample → defstream-0.1.14/samples}/Worker/Sample.py +0 -0
- {defstream-0.1.13 → defstream-0.1.14}/setup.cfg +0 -0
- {defstream-0.1.13 → defstream-0.1.14}/setup.py +0 -0
- {defstream-0.1.13 → defstream-0.1.14}/src/Broker/Configuration.py +0 -0
- {defstream-0.1.13 → defstream-0.1.14}/src/Broker/Connection.py +0 -0
- {defstream-0.1.13 → defstream-0.1.14}/src/Broker/Consumer.py +0 -0
- {defstream-0.1.13 → defstream-0.1.14}/src/Broker/Errors.py +0 -0
- {defstream-0.1.13 → defstream-0.1.14}/src/Broker/Event.py +0 -0
- {defstream-0.1.13 → defstream-0.1.14}/src/Broker/Implements/__init__.py +0 -0
- {defstream-0.1.13 → defstream-0.1.14}/src/Broker/Policies.py +0 -0
- {defstream-0.1.13 → defstream-0.1.14}/src/Broker/Priority.py +0 -0
- {defstream-0.1.13 → defstream-0.1.14}/src/Broker/Protocol.py +0 -0
- {defstream-0.1.13 → defstream-0.1.14}/src/Broker/__init__.py +0 -0
- {defstream-0.1.13 → defstream-0.1.14}/src/Descriptor/DataObject.py +0 -0
- {defstream-0.1.13 → defstream-0.1.14}/src/Descriptor/Types.py +0 -0
- {defstream-0.1.13 → defstream-0.1.14}/src/Descriptor/Value.py +0 -0
- {defstream-0.1.13 → defstream-0.1.14}/src/Descriptor/__init__.py +0 -0
- {defstream-0.1.13 → defstream-0.1.14}/src/Inspector/Extension.py +0 -0
- {defstream-0.1.13 → defstream-0.1.14}/src/Inspector/Extensions/Console.html +0 -0
- {defstream-0.1.13 → defstream-0.1.14}/src/Inspector/Extensions/Console.py +0 -0
- {defstream-0.1.13 → defstream-0.1.14}/src/Inspector/Extensions/Dashboard.html +0 -0
- {defstream-0.1.13 → defstream-0.1.14}/src/Inspector/Extensions/Dashboard.py +0 -0
- {defstream-0.1.13 → defstream-0.1.14}/src/Inspector/Extensions/HealthCheck.py +0 -0
- {defstream-0.1.13 → defstream-0.1.14}/src/Inspector/Extensions/Metrics.py +0 -0
- {defstream-0.1.13 → defstream-0.1.14}/src/Inspector/Extensions/Specifications.py +0 -0
- {defstream-0.1.13 → defstream-0.1.14}/src/Inspector/Extensions/__init__.py +0 -0
- {defstream-0.1.13 → defstream-0.1.14}/src/Inspector/Inspector.py +0 -0
- {defstream-0.1.13 → defstream-0.1.14}/src/Inspector/Response.py +0 -0
- {defstream-0.1.13 → defstream-0.1.14}/src/Inspector/__init__.py +0 -0
- {defstream-0.1.13 → defstream-0.1.14}/src/Validator/Pattern.py +0 -0
- {defstream-0.1.13 → defstream-0.1.14}/src/Validator/Patterns/Array.py +0 -0
- {defstream-0.1.13 → defstream-0.1.14}/src/Validator/Patterns/Compare.py +0 -0
- {defstream-0.1.13 → defstream-0.1.14}/src/Validator/Patterns/Condition.py +0 -0
- {defstream-0.1.13 → defstream-0.1.14}/src/Validator/Patterns/DataObject.py +0 -0
- {defstream-0.1.13 → defstream-0.1.14}/src/Validator/Patterns/DateTime.py +0 -0
- {defstream-0.1.13 → defstream-0.1.14}/src/Validator/Patterns/Number.py +0 -0
- {defstream-0.1.13 → defstream-0.1.14}/src/Validator/Patterns/Object.py +0 -0
- {defstream-0.1.13 → defstream-0.1.14}/src/Validator/Patterns/Size.py +0 -0
- {defstream-0.1.13 → defstream-0.1.14}/src/Validator/Patterns/String.py +0 -0
- {defstream-0.1.13 → defstream-0.1.14}/src/Validator/Patterns/Type.py +0 -0
- {defstream-0.1.13 → defstream-0.1.14}/src/Validator/Validate.py +0 -0
- {defstream-0.1.13 → defstream-0.1.14}/src/Validator/Validator.py +0 -0
- {defstream-0.1.13 → defstream-0.1.14}/src/Validator/__init__.py +0 -0
- {defstream-0.1.13 → defstream-0.1.14}/src/Worker/Executor.py +0 -0
- {defstream-0.1.13 → defstream-0.1.14}/src/Worker/Message.py +0 -0
- {defstream-0.1.13 → defstream-0.1.14}/src/Worker/Pool.py +0 -0
- {defstream-0.1.13 → defstream-0.1.14}/src/Worker/Run.py +0 -0
- {defstream-0.1.13 → defstream-0.1.14}/src/Worker/Specification.py +0 -0
- {defstream-0.1.13 → defstream-0.1.14}/src/Worker/Startup.py +0 -0
- {defstream-0.1.13 → defstream-0.1.14}/src/Worker/Worker.py +0 -0
- {defstream-0.1.13 → defstream-0.1.14}/src/Worker/__init__.py +0 -0
- {defstream-0.1.13 → defstream-0.1.14}/src/__init__.py +0 -0
- {defstream-0.1.13/test → defstream-0.1.14/tests}/test_dashboard.py +0 -0
- {defstream-0.1.13/test → defstream-0.1.14/tests}/test_dashboard_ui.cjs +0 -0
- {defstream-0.1.13/test → defstream-0.1.14/tests}/test_descriptor.py +0 -0
- {defstream-0.1.13/test → defstream-0.1.14/tests}/test_inspector.py +0 -0
- {defstream-0.1.13/test → defstream-0.1.14/tests}/test_inspector_console.py +0 -0
- {defstream-0.1.13/test → defstream-0.1.14/tests}/test_inspector_logging.py +0 -0
- {defstream-0.1.13/test → defstream-0.1.14/tests}/test_lifecycle_hooks.py +0 -0
- {defstream-0.1.13/test → defstream-0.1.14/tests}/test_pool_callbacks.py +0 -0
- {defstream-0.1.13/test → defstream-0.1.14/tests}/test_process_signals.py +0 -0
- {defstream-0.1.13/test → defstream-0.1.14/tests}/test_protocol_contracts.py +0 -0
- {defstream-0.1.13/test → defstream-0.1.14/tests}/test_runner_hooks.py +0 -0
- {defstream-0.1.13/test → defstream-0.1.14/tests}/test_specifications.py +0 -0
- {defstream-0.1.13/test → defstream-0.1.14/tests}/test_task_messages.py +0 -0
- {defstream-0.1.13/test → defstream-0.1.14/tests}/test_task_priorities.py +0 -0
- {defstream-0.1.13/test → defstream-0.1.14/tests}/test_worker.py +0 -0
- {defstream-0.1.13/test → defstream-0.1.14/tests}/test_worker_startup.py +0 -0
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
name: 변경 제안
|
|
2
|
+
description: 일반 변경이나 핫픽스의 목적과 범위를 정리합니다.
|
|
3
|
+
labels:
|
|
4
|
+
- fix
|
|
5
|
+
projects:
|
|
6
|
+
- yong5eon/7
|
|
7
|
+
body:
|
|
8
|
+
- type: markdown
|
|
9
|
+
attributes:
|
|
10
|
+
value: >
|
|
11
|
+
일반 변경이나 긴급 수정이 필요한 핫픽스를 제안할 때 사용해 주세요.
|
|
12
|
+
재현 가능한 기존 결함은 버그/오류 제보 양식을 이용해 주세요.
|
|
13
|
+
- type: dropdown
|
|
14
|
+
id: change_type
|
|
15
|
+
attributes:
|
|
16
|
+
label: 변경 유형
|
|
17
|
+
description: 제안하는 변경의 성격을 선택해 주세요.
|
|
18
|
+
options:
|
|
19
|
+
- 일반 변경
|
|
20
|
+
- 핫픽스
|
|
21
|
+
validations:
|
|
22
|
+
required: true
|
|
23
|
+
- type: textarea
|
|
24
|
+
id: purpose
|
|
25
|
+
attributes:
|
|
26
|
+
label: 변경 목적
|
|
27
|
+
description: 왜 이 변경이 필요한지, 해결하려는 불편이나 상황을 설명해 주세요.
|
|
28
|
+
validations:
|
|
29
|
+
required: true
|
|
30
|
+
- type: textarea
|
|
31
|
+
id: proposed_changes
|
|
32
|
+
attributes:
|
|
33
|
+
label: 제안하는 변경 내용
|
|
34
|
+
description: 무엇을 어떻게 바꾸면 좋을지 적어 주세요.
|
|
35
|
+
validations:
|
|
36
|
+
required: true
|
|
37
|
+
- type: textarea
|
|
38
|
+
id: scope
|
|
39
|
+
attributes:
|
|
40
|
+
label: 영향 범위
|
|
41
|
+
description: 영향을 받는 기능, 사용자, 호환성 또는 설정을 알고 있다면 적어 주세요.
|
|
42
|
+
validations:
|
|
43
|
+
required: false
|
|
44
|
+
- type: textarea
|
|
45
|
+
id: hotfix_context
|
|
46
|
+
attributes:
|
|
47
|
+
label: 긴급 수정 정보
|
|
48
|
+
description: 핫픽스인 경우 긴급한 이유, 영향받는 버전 및 임시 대응 방법을 적어 주세요.
|
|
49
|
+
validations:
|
|
50
|
+
required: false
|
|
51
|
+
- type: textarea
|
|
52
|
+
id: acceptance_criteria
|
|
53
|
+
attributes:
|
|
54
|
+
label: 완료 기준
|
|
55
|
+
description: 변경이 완료되었다고 판단할 수 있는 조건이나 검증 방법을 적어 주세요.
|
|
56
|
+
validations:
|
|
57
|
+
required: false
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
name: 작업 제안
|
|
2
|
+
description: 리소스 변경, 문서화 등 소스 코드 변경이 아닌 작업을 정리합니다.
|
|
3
|
+
labels:
|
|
4
|
+
- task
|
|
5
|
+
projects:
|
|
6
|
+
- yong5eon/7
|
|
7
|
+
body:
|
|
8
|
+
- type: markdown
|
|
9
|
+
attributes:
|
|
10
|
+
value: >
|
|
11
|
+
리소스 변경, 문서 작성·정리 등 소스 코드를 변경하지 않는 작업에 사용해 주세요.
|
|
12
|
+
기능 추가, 버그 제보 또는 소스 코드 변경은 해당 이슈 양식을 이용해 주세요.
|
|
13
|
+
- type: textarea
|
|
14
|
+
id: purpose
|
|
15
|
+
attributes:
|
|
16
|
+
label: 작업 목적
|
|
17
|
+
description: 이 작업이 필요한 이유와 기대하는 효과를 설명해 주세요.
|
|
18
|
+
validations:
|
|
19
|
+
required: true
|
|
20
|
+
- type: textarea
|
|
21
|
+
id: scope
|
|
22
|
+
attributes:
|
|
23
|
+
label: 작업 내용 및 대상
|
|
24
|
+
description: 수행할 작업과 대상 리소스, 문서 또는 경로를 적어 주세요.
|
|
25
|
+
validations:
|
|
26
|
+
required: true
|
|
27
|
+
- type: textarea
|
|
28
|
+
id: acceptance_criteria
|
|
29
|
+
attributes:
|
|
30
|
+
label: 완료 기준
|
|
31
|
+
description: 작업이 완료되었다고 판단할 수 있는 결과물이나 확인 방법을 적어 주세요.
|
|
32
|
+
validations:
|
|
33
|
+
required: true
|
|
34
|
+
- type: textarea
|
|
35
|
+
id: additional
|
|
36
|
+
attributes:
|
|
37
|
+
label: 관련 자료 및 주의사항
|
|
38
|
+
description: 참고 링크, 관련 이슈, 사전 준비나 주의사항이 있다면 적어 주세요.
|
|
39
|
+
validations:
|
|
40
|
+
required: false
|
|
@@ -33,6 +33,7 @@ jobs:
|
|
|
33
33
|
core_ref: ${{ steps.refs.outputs.core_ref }}
|
|
34
34
|
rabbitmq_ref: ${{ steps.refs.outputs.rabbitmq_ref }}
|
|
35
35
|
redis_ref: ${{ steps.refs.outputs.redis_ref }}
|
|
36
|
+
test_required: ${{ steps.test_paths.outputs.required }}
|
|
36
37
|
steps:
|
|
37
38
|
- uses: actions/checkout@v7
|
|
38
39
|
with:
|
|
@@ -42,6 +43,28 @@ jobs:
|
|
|
42
43
|
uses: actions/setup-python@v7
|
|
43
44
|
with:
|
|
44
45
|
python-version: '3.13'
|
|
46
|
+
- name: Detect test-relevant changes
|
|
47
|
+
id: test_paths
|
|
48
|
+
run: |
|
|
49
|
+
python - <<'PY'
|
|
50
|
+
from json import loads
|
|
51
|
+
from os import environ
|
|
52
|
+
from pathlib import Path
|
|
53
|
+
from subprocess import check_output
|
|
54
|
+
|
|
55
|
+
required = True
|
|
56
|
+
if environ['GITHUB_EVENT_NAME'] == 'pull_request':
|
|
57
|
+
event = loads(Path(environ['GITHUB_EVENT_PATH']).read_text(encoding='utf-8'))
|
|
58
|
+
base = event['pull_request']['base']['sha']
|
|
59
|
+
changed = check_output([
|
|
60
|
+
'git', 'diff', '--name-only', '--no-renames', '-z',
|
|
61
|
+
f'{base}...{environ["GITHUB_SHA"]}', '--', 'samples/', 'src/', 'tests/', 'setup.py',
|
|
62
|
+
])
|
|
63
|
+
required = bool(changed)
|
|
64
|
+
with Path(environ['GITHUB_OUTPUT']).open('a', encoding='utf-8') as output:
|
|
65
|
+
output.write(f'required={str(required).lower()}\n')
|
|
66
|
+
print(f'Test-relevant changes: {required}')
|
|
67
|
+
PY
|
|
45
68
|
- name: Check complete push range and plan version
|
|
46
69
|
id: changes
|
|
47
70
|
env:
|
|
@@ -224,6 +247,7 @@ jobs:
|
|
|
224
247
|
test:
|
|
225
248
|
name: Test Python ${{ matrix.python }}
|
|
226
249
|
needs: changes
|
|
250
|
+
if: needs.changes.outputs.test_required == 'true'
|
|
227
251
|
runs-on: ubuntu-latest
|
|
228
252
|
timeout-minutes: 25
|
|
229
253
|
strategy:
|
|
@@ -384,8 +408,12 @@ jobs:
|
|
|
384
408
|
- name: Test installed package
|
|
385
409
|
run: |
|
|
386
410
|
cd "$RUNNER_TEMP"
|
|
411
|
+
test_directory=test
|
|
412
|
+
if [ "$PROJECT" = "DefStream" ]; then
|
|
413
|
+
test_directory=tests
|
|
414
|
+
fi
|
|
387
415
|
"$RUNNER_TEMP/installed/bin/python" -m unittest discover \
|
|
388
|
-
-s "$GITHUB_WORKSPACE/packages/$PROJECT
|
|
416
|
+
-s "$GITHUB_WORKSPACE/packages/$PROJECT/$test_directory" -p 'test_*.py' -v
|
|
389
417
|
|
|
390
418
|
- name: Set up Node for core UI tests
|
|
391
419
|
if: env.PROJECT == 'DefStream'
|
|
@@ -395,7 +423,7 @@ jobs:
|
|
|
395
423
|
|
|
396
424
|
- name: Test core UI
|
|
397
425
|
if: env.PROJECT == 'DefStream'
|
|
398
|
-
run: node --test packages/DefStream/
|
|
426
|
+
run: node --test packages/DefStream/tests/test_dashboard_ui.cjs
|
|
399
427
|
|
|
400
428
|
- name: Preserve verified release distributions
|
|
401
429
|
if: needs.changes.outputs.release == 'true' && matrix.python == '3.13'
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: DefStream
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.14
|
|
4
4
|
Summary: Synchronous message processing with pluggable broker adapters
|
|
5
5
|
Home-page: https://github.com/yong5eon/DefStream
|
|
6
6
|
Author: Heo Yongseon
|
|
@@ -109,8 +109,8 @@ ProcessPool은 `spawn` 자식 프로세스를 사용하므로 부모의 핸들
|
|
|
109
109
|
자식도 로그를 출력하려면 import 가능한 `PoolSetup` 구현에서 같은 설정을 적용하고
|
|
110
110
|
`ProcessPool(..., setups=...)`로 전달하세요. 자식 초기화 훅이 실행되기 전의 DEBUG·INFO는
|
|
111
111
|
그 설정으로 수신할 수 없습니다.
|
|
112
|
-
[RabbitMQ 작업 예제의 LoggingSetup](./
|
|
113
|
-
[부모·자식 설정 예제](./
|
|
112
|
+
[RabbitMQ 작업 예제의 LoggingSetup](./samples/Worker/RabbitMQ/Tasks.py)과
|
|
113
|
+
[부모·자식 설정 예제](./samples/Worker/RabbitMQ/Worker.py)를 참고하세요.
|
|
114
114
|
기존 애플리케이션에서는 이미 설정한 핸들러를 반복 추가하지 않도록 초기화 위치를 관리해야 합니다.
|
|
115
115
|
|
|
116
116
|
## 설치
|
|
@@ -671,9 +671,9 @@ Console의 `broker` 인자는 `DefStream.Broker.BrokerFactory` 계약을 사용
|
|
|
671
671
|
|
|
672
672
|
## 예제와 라이선스
|
|
673
673
|
|
|
674
|
-
- [브로커 없이 실행하는 Worker 예제](./
|
|
675
|
-
- [RabbitMQ Worker·RPC 클라이언트 예제](./
|
|
676
|
-
- [Redis Worker 예제](./
|
|
674
|
+
- [브로커 없이 실행하는 Worker 예제](./samples/Worker/Sample.py)
|
|
675
|
+
- [RabbitMQ Worker·RPC 클라이언트 예제](./samples/Worker/RabbitMQ)
|
|
676
|
+
- [Redis Worker 예제](./samples/Worker/Redis/Sample.py)
|
|
677
677
|
- [릴리즈와 변경 내역](https://github.com/yong5eon/DefStream/releases)
|
|
678
678
|
|
|
679
679
|
GNU GPL v3 라이선스를 사용합니다. 자세한 조건은 [LICENSE](./LICENSE)를 확인하세요.
|
|
@@ -4,10 +4,11 @@ README.en.md
|
|
|
4
4
|
README.md
|
|
5
5
|
setup.py
|
|
6
6
|
.github/PULL_REQUEST_TEMPLATE.md
|
|
7
|
-
.github/ISSUE_TEMPLATE/
|
|
7
|
+
.github/ISSUE_TEMPLATE/01.feature.yml
|
|
8
|
+
.github/ISSUE_TEMPLATE/02.bug.yml
|
|
9
|
+
.github/ISSUE_TEMPLATE/03.fix.yml
|
|
10
|
+
.github/ISSUE_TEMPLATE/04.task.yml
|
|
8
11
|
.github/ISSUE_TEMPLATE/config.yml
|
|
9
|
-
.github/ISSUE_TEMPLATE/feature_request.yml
|
|
10
|
-
.github/PULL_REQUEST_TEMPLATE/hotfix.md
|
|
11
12
|
.github/workflows/ci.yml
|
|
12
13
|
DefStream.egg-info/PKG-INFO
|
|
13
14
|
DefStream.egg-info/SOURCES.txt
|
|
@@ -31,6 +32,10 @@ issues/fix/10/IMPLEMENTS.md
|
|
|
31
32
|
issues/fix/10/README.md
|
|
32
33
|
issues/fix/10/REQUIREMENTS.md
|
|
33
34
|
issues/fix/13/README.md
|
|
35
|
+
issues/fix/21/IMPLEMENTS.md
|
|
36
|
+
issues/fix/21/ISSUE.md
|
|
37
|
+
issues/fix/21/README.md
|
|
38
|
+
issues/fix/21/REQUIREMENTS.md
|
|
34
39
|
issues/fix/3/IMPLEMENTS.md
|
|
35
40
|
issues/fix/3/README.md
|
|
36
41
|
issues/fix/3/REQUIREMENTS.md
|
|
@@ -38,12 +43,15 @@ issues/fix/3/ci.refs.json
|
|
|
38
43
|
issues/fix/6/IMPLEMENTS.md
|
|
39
44
|
issues/fix/6/README.md
|
|
40
45
|
issues/fix/6/REQUIREMENTS.md
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
46
|
+
issues/task/18/IMPLEMENTS.md
|
|
47
|
+
issues/task/18/README.md
|
|
48
|
+
issues/task/18/REQUIREMENTS.md
|
|
49
|
+
samples/Broker/Sample.py
|
|
50
|
+
samples/Worker/Sample.py
|
|
51
|
+
samples/Worker/RabbitMQ/Client.py
|
|
52
|
+
samples/Worker/RabbitMQ/Tasks.py
|
|
53
|
+
samples/Worker/RabbitMQ/Worker.py
|
|
54
|
+
samples/Worker/Redis/Sample.py
|
|
47
55
|
src/__init__.py
|
|
48
56
|
src/Broker/Configuration.py
|
|
49
57
|
src/Broker/Connection.py
|
|
@@ -95,21 +103,22 @@ src/Worker/Specification.py
|
|
|
95
103
|
src/Worker/Startup.py
|
|
96
104
|
src/Worker/Worker.py
|
|
97
105
|
src/Worker/__init__.py
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
106
|
+
tests/test_dashboard.py
|
|
107
|
+
tests/test_dashboard_ui.cjs
|
|
108
|
+
tests/test_descriptor.py
|
|
109
|
+
tests/test_inspector.py
|
|
110
|
+
tests/test_inspector_console.py
|
|
111
|
+
tests/test_inspector_logging.py
|
|
112
|
+
tests/test_lifecycle_hooks.py
|
|
113
|
+
tests/test_logging.py
|
|
114
|
+
tests/test_pool_callbacks.py
|
|
115
|
+
tests/test_process_signals.py
|
|
116
|
+
tests/test_protocol_contracts.py
|
|
117
|
+
tests/test_release_workflow.py
|
|
118
|
+
tests/test_runner_hooks.py
|
|
119
|
+
tests/test_specifications.py
|
|
120
|
+
tests/test_task_messages.py
|
|
121
|
+
tests/test_task_priorities.py
|
|
122
|
+
tests/test_validator_patterns.py
|
|
123
|
+
tests/test_worker.py
|
|
124
|
+
tests/test_worker_startup.py
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: DefStream
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.14
|
|
4
4
|
Summary: Synchronous message processing with pluggable broker adapters
|
|
5
5
|
Home-page: https://github.com/yong5eon/DefStream
|
|
6
6
|
Author: Heo Yongseon
|
|
@@ -109,8 +109,8 @@ ProcessPool은 `spawn` 자식 프로세스를 사용하므로 부모의 핸들
|
|
|
109
109
|
자식도 로그를 출력하려면 import 가능한 `PoolSetup` 구현에서 같은 설정을 적용하고
|
|
110
110
|
`ProcessPool(..., setups=...)`로 전달하세요. 자식 초기화 훅이 실행되기 전의 DEBUG·INFO는
|
|
111
111
|
그 설정으로 수신할 수 없습니다.
|
|
112
|
-
[RabbitMQ 작업 예제의 LoggingSetup](./
|
|
113
|
-
[부모·자식 설정 예제](./
|
|
112
|
+
[RabbitMQ 작업 예제의 LoggingSetup](./samples/Worker/RabbitMQ/Tasks.py)과
|
|
113
|
+
[부모·자식 설정 예제](./samples/Worker/RabbitMQ/Worker.py)를 참고하세요.
|
|
114
114
|
기존 애플리케이션에서는 이미 설정한 핸들러를 반복 추가하지 않도록 초기화 위치를 관리해야 합니다.
|
|
115
115
|
|
|
116
116
|
## 설치
|
|
@@ -671,9 +671,9 @@ Console의 `broker` 인자는 `DefStream.Broker.BrokerFactory` 계약을 사용
|
|
|
671
671
|
|
|
672
672
|
## 예제와 라이선스
|
|
673
673
|
|
|
674
|
-
- [브로커 없이 실행하는 Worker 예제](./
|
|
675
|
-
- [RabbitMQ Worker·RPC 클라이언트 예제](./
|
|
676
|
-
- [Redis Worker 예제](./
|
|
674
|
+
- [브로커 없이 실행하는 Worker 예제](./samples/Worker/Sample.py)
|
|
675
|
+
- [RabbitMQ Worker·RPC 클라이언트 예제](./samples/Worker/RabbitMQ)
|
|
676
|
+
- [Redis Worker 예제](./samples/Worker/Redis/Sample.py)
|
|
677
677
|
- [릴리즈와 변경 내역](https://github.com/yong5eon/DefStream/releases)
|
|
678
678
|
|
|
679
679
|
GNU GPL v3 라이선스를 사용합니다. 자세한 조건은 [LICENSE](./LICENSE)를 확인하세요.
|
|
@@ -27,15 +27,66 @@ Configure execution, acknowledgements, failure policies, and monitoring without
|
|
|
27
27
|
- [Lifecycle hooks](#lifecycle-hooks)
|
|
28
28
|
- [Request/reply contracts and validation](#requestreply-contracts-and-validation)
|
|
29
29
|
- [Health checks and task console](#health-checks-and-task-console)
|
|
30
|
+
- [Logging](#logging)
|
|
30
31
|
- [Broker selection and operational considerations](#broker-selection-and-operational-considerations)
|
|
31
32
|
- [Examples and license](#examples-and-license)
|
|
32
33
|
|
|
33
|
-
##
|
|
34
|
+
## Logging
|
|
34
35
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
36
|
+
DefStream records messages through standard `logging` without configuring handlers,
|
|
37
|
+
formatters, or levels. Select the sources your application needs. The samples
|
|
38
|
+
output only the `Sample` and `DefStream` logger hierarchies, replacing their
|
|
39
|
+
`print()` calls with logging. The Worker's existing startup banner is still
|
|
40
|
+
printed regardless of logging configuration.
|
|
41
|
+
|
|
42
|
+
```python
|
|
43
|
+
from logging import DEBUG, Filter, Formatter, StreamHandler, getLogger
|
|
44
|
+
|
|
45
|
+
sources = (Filter('Sample'), Filter('DefStream'))
|
|
46
|
+
handler = StreamHandler()
|
|
47
|
+
handler.setFormatter(Formatter(
|
|
48
|
+
'%(asctime)s %(processName)s %(name)s %(levelname)s %(message)s'
|
|
49
|
+
))
|
|
50
|
+
handler.addFilter(lambda record: any(source.filter(record) for source in sources))
|
|
51
|
+
root = getLogger()
|
|
52
|
+
root.setLevel(DEBUG)
|
|
53
|
+
root.addHandler(handler)
|
|
54
|
+
|
|
55
|
+
logger = getLogger('Sample')
|
|
56
|
+
logger.info('Application started')
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Apply filters to the **handler**, not the root logger. `Filter('DefStream')`
|
|
60
|
+
includes `DefStream` and names below `DefStream.`, but not `DefStreamExtra`.
|
|
61
|
+
This configuration is an example for a standalone application; it does not change
|
|
62
|
+
output from other handlers already installed. To receive only broker logs, select
|
|
63
|
+
`DefStream.Broker.Implements.RabbitMQ` or `DefStream.Broker.Implements.Redis`
|
|
64
|
+
instead of `DefStream`.
|
|
65
|
+
|
|
66
|
+
- The class member `logger` uses `DefStream.Worker`, `DefStream.Run`,
|
|
67
|
+
`DefStream.Executor`, `DefStream.Pool`, `DefStream.ThreadPool`, and
|
|
68
|
+
`DefStream.ProcessPool`.
|
|
69
|
+
- Shared Pool methods also use the concrete pool's logger member. User subclasses
|
|
70
|
+
inherit the default name and can explicitly override `logger`.
|
|
71
|
+
- Inspector, Server, and RequestHandler share `DefStream.Inspector`.
|
|
72
|
+
HTTP request receipt is DEBUG; response status and transmission results are INFO.
|
|
73
|
+
Extension-specific logs use `DefStream.Inspector.Extensions.<extension name>`.
|
|
74
|
+
- Normal per-message processing is DEBUG, lifecycle events are INFO, events
|
|
75
|
+
requiring attention are WARNING, and processing failures are ERROR.
|
|
76
|
+
Bodies, results, and credentials are excluded from the default log context.
|
|
77
|
+
- Without any handlers, Python's `lastResort` may write WARNING and higher to
|
|
78
|
+
stderr. Do not put sensitive values in user exception messages: failure
|
|
79
|
+
tracebacks include those messages.
|
|
80
|
+
|
|
81
|
+
ProcessPool uses `spawn` child processes, so parent handlers are not automatically
|
|
82
|
+
inherited. To receive child logs, apply the same configuration in an importable
|
|
83
|
+
`PoolSetup` implementation and pass it through `ProcessPool(..., setups=...)`.
|
|
84
|
+
That configuration cannot capture DEBUG and INFO logs emitted before the child
|
|
85
|
+
setup hook runs. See
|
|
86
|
+
[LoggingSetup in the RabbitMQ task example](./samples/Worker/RabbitMQ/Tasks.py)
|
|
87
|
+
and the [parent/child configuration example](./samples/Worker/RabbitMQ/Worker.py).
|
|
88
|
+
In existing applications, choose the initialization location carefully to avoid
|
|
89
|
+
adding the same handlers repeatedly.
|
|
39
90
|
|
|
40
91
|
## Installation
|
|
41
92
|
|
|
@@ -610,9 +661,9 @@ For a class-based factory, you can inherit `BrokerFactory` and implement `__call
|
|
|
610
661
|
|
|
611
662
|
## Examples and license
|
|
612
663
|
|
|
613
|
-
- [Worker without an external broker](./
|
|
614
|
-
- [RabbitMQ Worker and RPC client](./
|
|
615
|
-
- [Redis Worker](./
|
|
664
|
+
- [Worker without an external broker](./samples/Worker/Sample.py)
|
|
665
|
+
- [RabbitMQ Worker and RPC client](./samples/Worker/RabbitMQ)
|
|
666
|
+
- [Redis Worker](./samples/Worker/Redis/Sample.py)
|
|
616
667
|
- [Releases and change history](https://github.com/yong5eon/DefStream/releases)
|
|
617
668
|
|
|
618
669
|
Licensed under GNU GPL v3. See [LICENSE](./LICENSE) for the terms.
|
|
@@ -76,8 +76,8 @@ ProcessPool은 `spawn` 자식 프로세스를 사용하므로 부모의 핸들
|
|
|
76
76
|
자식도 로그를 출력하려면 import 가능한 `PoolSetup` 구현에서 같은 설정을 적용하고
|
|
77
77
|
`ProcessPool(..., setups=...)`로 전달하세요. 자식 초기화 훅이 실행되기 전의 DEBUG·INFO는
|
|
78
78
|
그 설정으로 수신할 수 없습니다.
|
|
79
|
-
[RabbitMQ 작업 예제의 LoggingSetup](./
|
|
80
|
-
[부모·자식 설정 예제](./
|
|
79
|
+
[RabbitMQ 작업 예제의 LoggingSetup](./samples/Worker/RabbitMQ/Tasks.py)과
|
|
80
|
+
[부모·자식 설정 예제](./samples/Worker/RabbitMQ/Worker.py)를 참고하세요.
|
|
81
81
|
기존 애플리케이션에서는 이미 설정한 핸들러를 반복 추가하지 않도록 초기화 위치를 관리해야 합니다.
|
|
82
82
|
|
|
83
83
|
## 설치
|
|
@@ -638,9 +638,9 @@ Console의 `broker` 인자는 `DefStream.Broker.BrokerFactory` 계약을 사용
|
|
|
638
638
|
|
|
639
639
|
## 예제와 라이선스
|
|
640
640
|
|
|
641
|
-
- [브로커 없이 실행하는 Worker 예제](./
|
|
642
|
-
- [RabbitMQ Worker·RPC 클라이언트 예제](./
|
|
643
|
-
- [Redis Worker 예제](./
|
|
641
|
+
- [브로커 없이 실행하는 Worker 예제](./samples/Worker/Sample.py)
|
|
642
|
+
- [RabbitMQ Worker·RPC 클라이언트 예제](./samples/Worker/RabbitMQ)
|
|
643
|
+
- [Redis Worker 예제](./samples/Worker/Redis/Sample.py)
|
|
644
644
|
- [릴리즈와 변경 내역](https://github.com/yong5eon/DefStream/releases)
|
|
645
645
|
|
|
646
646
|
GNU GPL v3 라이선스를 사용합니다. 자세한 조건은 [LICENSE](./LICENSE)를 확인하세요.
|
|
@@ -62,11 +62,11 @@ HealthCheck는 probe 예약·응답·판정과 응답 생성을 DEBUG로 기록
|
|
|
62
62
|
- 런타임 로그 메시지는 영어로 작성하고 한국어 문서·주석은 유지한다.
|
|
63
63
|
- 본문·결과·인증정보를 기본 문맥에 넣지 않는다. 단, Worker의 작업 실패
|
|
64
64
|
traceback에는 사용자 예외 메시지가 포함될 수 있으므로 사용자가 주의해야 한다.
|
|
65
|
-
- [Worker 샘플](../../../
|
|
65
|
+
- [Worker 샘플](../../../samples/Worker)과 [Broker 샘플](../../../samples/Broker)은
|
|
66
66
|
`Sample`과 `DefStream` 계층만 핸들러 필터로 선택한다.
|
|
67
67
|
- 샘플의 `print()`는 로그로 전환하고 라이브러리 시작 배너는 유지했다.
|
|
68
|
-
- [RabbitMQ Worker 샘플](../../../
|
|
69
|
-
ProcessPool의 `setups`에 [LoggingSetup](../../../
|
|
68
|
+
- [RabbitMQ Worker 샘플](../../../samples/Worker/RabbitMQ/Worker.py)은 부모 진입점과
|
|
69
|
+
ProcessPool의 `setups`에 [LoggingSetup](../../../samples/Worker/RabbitMQ/Tasks.py)을
|
|
70
70
|
적용한다. `spawn` 자식이 부모의 핸들러를 자동 상속한다고 가정하지 않는다.
|
|
71
71
|
|
|
72
72
|
## 6. 검증 결과
|
|
@@ -81,9 +81,9 @@ Python 3.13.16에서 실제 RabbitMQ·Redis가 실행 중인 환경으로 검증
|
|
|
81
81
|
| 세 프로젝트 소스·샘플의 로그 및 observe 호출 문자열 | 376곳 점검, 한국어 문자열 없음 |
|
|
82
82
|
| 세 프로젝트 소스·샘플 `compileall` 및 `git diff --check` | 통과 |
|
|
83
83
|
|
|
84
|
-
[로깅 테스트](../../../
|
|
84
|
+
[로깅 테스트](../../../tests/test_logging.py)는 클래스 멤버·상속·사용자 재정의,
|
|
85
85
|
레벨·본문 제외·작업 실패 traceback 중복 방지·배너 유지·샘플 필터·spawn 설정을
|
|
86
|
-
검증한다. [Inspector 로깅 테스트](../../../
|
|
86
|
+
검증한다. [Inspector 로깅 테스트](../../../tests/test_inspector_logging.py)는 실제 HTTP
|
|
87
87
|
요청에서 수신·응답 각 1회 기록, 쿼리·본문 제외, WSGI 500과 전송 중단을 검증한다.
|
|
88
88
|
기존 테스트의 이전 모듈 로거 기대값도 새 이름과 레벨에 맞췄다.
|
|
89
89
|
|
|
@@ -34,7 +34,7 @@ Pool 공통 동작도 실제 ThreadPool·ProcessPool의 로거 이름으로 기
|
|
|
34
34
|
## 샘플 변경
|
|
35
35
|
|
|
36
36
|
샘플은 `print()` 대신 `Sample` 로거를 사용하며 `Sample`과 `DefStream` 계층만
|
|
37
|
-
출력합니다. [RabbitMQ Worker 샘플](../../../
|
|
38
|
-
부모와 spawn 자식에 [LoggingSetup](../../../
|
|
37
|
+
출력합니다. [RabbitMQ Worker 샘플](../../../samples/Worker/RabbitMQ/Worker.py)은
|
|
38
|
+
부모와 spawn 자식에 [LoggingSetup](../../../samples/Worker/RabbitMQ/Tasks.py)을 적용합니다.
|
|
39
39
|
실제 애플리케이션도 ProcessPool 자식의 로깅을 별도로 설정해야 합니다.
|
|
40
40
|
설정 예제는 [사용 설명서](../../../README.md#로깅)를 참고하세요.
|
|
@@ -29,8 +29,8 @@
|
|
|
29
29
|
- [Specification](../../../src/Worker/Specification.py)에서 `description` 인자와
|
|
30
30
|
AsyncAPI 메시지 설명 생성을 제거했다. schema, validator, example, format은
|
|
31
31
|
유지한다.
|
|
32
|
-
- [RabbitMQ Worker 샘플](../../../
|
|
33
|
-
[Redis Worker 샘플](../../../
|
|
32
|
+
- [RabbitMQ Worker 샘플](../../../samples/Worker/RabbitMQ/Tasks.py)과
|
|
33
|
+
[Redis Worker 샘플](../../../samples/Worker/Redis/Sample.py)에 `add`, `divide`
|
|
34
34
|
이름 및 작업 설명을 지정했다. RabbitMQ 샘플의 request·response
|
|
35
35
|
Specification 설명은 Run의 메타데이터로 옮겼다.
|
|
36
36
|
- [한국어 사용 설명서](../../../README.md)와
|
|
@@ -117,7 +117,7 @@ Python 3.9.13과 3.10.11에서 클래스 정의의 `name=` 키워드가
|
|
|
117
117
|
처리는 계속 `Run.__init_subclass__`가 담당한다. 사용자 클래스 정의 문법은
|
|
118
118
|
변경하지 않으며 `ABCMeta`의 추상 메서드 검사도 유지한다.
|
|
119
119
|
|
|
120
|
-
[Worker 테스트](../../../
|
|
120
|
+
[Worker 테스트](../../../tests/test_worker.py)에 이름을 지정한 추상 Run의 생성 거부,
|
|
121
121
|
구체 하위 Run의 이름 재정의 및 실행을 검증하는 회귀 테스트를 추가했다.
|
|
122
122
|
|
|
123
123
|
| Python | 전체 코어 테스트 결과 |
|
|
@@ -8,7 +8,7 @@ Worker 시작 배너를 로깅 설정 여부와 관계없이 먼저 확인할
|
|
|
8
8
|
|
|
9
9
|
## 변경 내용
|
|
10
10
|
|
|
11
|
-
- [Worker 샘플](../../../
|
|
11
|
+
- [Worker 샘플](../../../samples/Worker/Sample.py)은 `configure_logging()`을
|
|
12
12
|
실행 진입점에서 호출하는 대신 `SetupLogger` setup 훅에서 수행합니다.
|
|
13
13
|
Worker 생성·작업 등록 시점의 로그는 아직 설정되지 않은 핸들러에 의해 출력되지
|
|
14
14
|
않으며, 시작 배너가 샘플의 첫 화면 출력이 됩니다.
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# Validator `IsOptional` 변경 구현 기록
|
|
2
|
+
|
|
3
|
+
## 1. 구현 개요
|
|
4
|
+
|
|
5
|
+
[요구사항 명세서](./REQUIREMENTS.md)에 따라 Validator 패턴의 공개 이름을
|
|
6
|
+
`IsToNone`에서 `IsOptional`로 변경했다. 패턴의 입력 처리와 후속 패턴 실행
|
|
7
|
+
동작은 유지하고 기존 이름은 제거했다.
|
|
8
|
+
|
|
9
|
+
- 구현·검증일: 2026-10-21
|
|
10
|
+
- 사용자 관점의 변경 요약: 선택적 값을 처리하는 Validator 패턴 이름을 `IsOptional`로 통일
|
|
11
|
+
|
|
12
|
+
## 2. 변경 내용
|
|
13
|
+
|
|
14
|
+
- [Common.py](../../../src/Validator/Patterns/Common.py)에서 클래스를
|
|
15
|
+
`IsToNone`에서 `IsOptional`로 변경하고 모듈의 `__all__`을 갱신했다.
|
|
16
|
+
- [Patterns/__init__.py](../../../src/Validator/Patterns/__init__.py)에서
|
|
17
|
+
`IsOptional`을 가져오고 패키지 `__all__`에 공개했다.
|
|
18
|
+
- 기존 클래스명과 호환 별칭은 제공하지 않는다. 기존 `IsToNone`을 import하는
|
|
19
|
+
코드는 `IsOptional`로 변경해야 한다.
|
|
20
|
+
- `None`이면 후속 패턴을 실행하지 않고 그대로 반환하며, 그 외 값에는 전달된
|
|
21
|
+
패턴을 순서대로 적용한다. `repr`은 새 클래스명을 표시한다.
|
|
22
|
+
- [test_validator_patterns.py](../../../tests/test_validator_patterns.py)에
|
|
23
|
+
`None` 처리, 패턴 적용 순서, 예외 전파, 공개 export 및 표현 결과를 확인하는
|
|
24
|
+
테스트 5개를 추가했다.
|
|
25
|
+
|
|
26
|
+
## 3. 검증 결과
|
|
27
|
+
|
|
28
|
+
| 검증 항목 | 결과 |
|
|
29
|
+
|---|---|
|
|
30
|
+
| 신규 Validator 패턴 단위 테스트 | 5개 통과 |
|
|
31
|
+
| 테스트 파일 직접 실행 도구 | 테스트를 찾지 못함 |
|
|
32
|
+
| Python unittest 직접 실행 | 통과. 저장소의 `src` 패키지를 `DefStream` 이름으로 등록해 테스트 실행 |
|
|
33
|
+
| 기존 이름 검색 | 소스의 구현 및 공개 export에서 제거 확인. 테스트는 미노출을 검증하기 위해 이름을 참조 |
|
|
34
|
+
|
|
35
|
+
테스트는 `python -m unittest discover`의 기본 import 방식으로는 저장소 패키지
|
|
36
|
+
이름을 찾지 못해 실행되지 않았다. 테스트 코드에서 현재 소스 패키지를
|
|
37
|
+
`DefStream`으로 등록한 뒤 unittest discovery를 실행하여 검증했다. 다른 테스트
|
|
38
|
+
파일이나 전체 테스트 스위트는 실행하지 않았다.
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
### 변경 유형
|
|
2
|
+
|
|
3
|
+
일반 변경
|
|
4
|
+
|
|
5
|
+
### 변경 목적
|
|
6
|
+
|
|
7
|
+
Validator 패턴 중 IsToNone 의 이름이 파이썬에서 사용하는 Optional 처럼 동작해야 해서, 좀더 친숙한 이름으로 변경을 제안
|
|
8
|
+
|
|
9
|
+
### 제안하는 변경 내용
|
|
10
|
+
|
|
11
|
+
이름 변경 후보:
|
|
12
|
+
|
|
13
|
+
- Optional: Python 에서 Optional 을 많이 사용하여 사용 시 알리아스가 필요
|
|
14
|
+
- IsOptional
|
|
15
|
+
- ToOptional
|
|
16
|
+
- AsOptional
|
|
17
|
+
- OfOptional
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# Validator 패턴 이름을 `IsOptional`로 변경
|
|
2
|
+
|
|
3
|
+
## 변경 요약
|
|
4
|
+
|
|
5
|
+
Validator 패턴의 이름을 `IsToNone`에서 `IsOptional`로 변경했습니다.
|
|
6
|
+
`None` 입력은 그대로 반환하고, 그 외 입력에는 지정한 패턴을 순서대로 적용합니다.
|
|
7
|
+
처리 동작은 달라지지 않았으며 이름만 더 알아보기 쉽게 바뀌었습니다.
|
|
8
|
+
|
|
9
|
+
## 기존 코드에서 바꿀 부분
|
|
10
|
+
|
|
11
|
+
기존 `IsToNone` import와 사용 코드를 `IsOptional`로 변경하세요.
|
|
12
|
+
`IsToNone`은 호환 별칭으로 제공되지 않습니다.
|
|
13
|
+
|
|
14
|
+
변경 전:
|
|
15
|
+
|
|
16
|
+
```python
|
|
17
|
+
from DefStream.Validator.Patterns import IsToNone
|
|
18
|
+
|
|
19
|
+
validator = IsToNone(pattern)
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
변경 후:
|
|
23
|
+
|
|
24
|
+
```python
|
|
25
|
+
from DefStream.Validator.Patterns import IsOptional
|
|
26
|
+
|
|
27
|
+
validator = IsOptional(pattern)
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
`IsOptional`은 Python의 `typing.Optional`이 아니라 런타임 입력값을 처리하는
|
|
31
|
+
Validator 패턴입니다.
|
|
32
|
+
|
|
33
|
+
## 검증
|
|
34
|
+
|
|
35
|
+
- `None` 입력 시 후속 패턴을 실행하지 않고 `None` 반환
|
|
36
|
+
- 비`None` 입력 시 후속 패턴을 순서대로 실행
|
|
37
|
+
- 후속 패턴의 예외 전파 및 `repr` 결과 확인
|
|
38
|
+
- 패키지 공개 export와 기존 이름 미노출 확인
|
|
39
|
+
- 신규 단위 테스트 5개 통과
|
|
40
|
+
|
|
41
|
+
## 상세 기록
|
|
42
|
+
|
|
43
|
+
- [요구사항 명세서](./REQUIREMENTS.md)
|
|
44
|
+
- [구현 및 검증 기록](./IMPLEMENTS.md)
|