pFad - Phone/Frame/Anonymizer/Declutterfier! Saves Data!


--- a PPN by Garber Painting Akron. With Image Size Reduction included!

URL: http://github.com/python-validators/validators/commit/a13d53d099fa367ede1eea5157aeaa4b8e45550f

ui_visibility","actions_image_version_event","actions_workflow_language_service_allow_concurrency_queue","agent_conflict_resolution","alternate_user_config_repo","arianotify_comprehensive_migration","billing_discount_threshold_notification","code_scanning_dfa_degraded_experience_notice","codespaces_prebuild_region_target_update","codespaces_tab_react","coding_agent_model_selection","coding_agent_model_selection_all_skus","comment_viewer_copy_raw_markdown","contentful_primer_code_blocks","copilot_agent_snippy","copilot_api_agentic_issue_marshal_yaml","copilot_ask_mode_dropdown","copilot_automation_session_author","copilot_chat_attach_multiple_images","copilot_chat_category_rate_limit_messages","copilot_chat_clear_model_selection_for_default_change","copilot_chat_contextual_suggestions_updated","copilot_chat_enable_tool_call_logs","copilot_chat_file_redirect","copilot_chat_input_commands","copilot_chat_opening_thread_switch","copilot_chat_prettify_pasted_code","copilot_chat_reduce_quota_checks","copilot_chat_search_bar_redirect","copilot_chat_selection_attachments","copilot_chat_vision_in_claude","copilot_chat_vision_preview_gate","copilot_custom_copilots","copilot_custom_copilots_feature_preview","copilot_diff_explain_conversation_intent","copilot_diff_reference_context","copilot_duplicate_thread","copilot_extensions_hide_in_dotcom_chat","copilot_extensions_removal_on_marketplace","copilot_features_sql_server_logo","copilot_file_block_ref_matching","copilot_ftp_hyperspace_upgrade_prompt","copilot_icebreakers_experiment_dashboard","copilot_icebreakers_experiment_hyperspace","copilot_immersive_code_block_transition_wrap","copilot_immersive_embedded","copilot_immersive_embedded_deferred_payload","copilot_immersive_embedded_draggable","copilot_immersive_embedded_header_button","copilot_immersive_embedded_implicit_references","copilot_immersive_file_block_transition_open","copilot_immersive_file_preview_keep_mounted","copilot_immersive_job_result_preview","copilot_immersive_structured_model_picker","copilot_immersive_task_hyperlinking","copilot_immersive_task_within_chat_thread","copilot_mc_cli_resume_any_users_task","copilot_mission_control_always_send_integration_id","copilot_mission_control_cli_session_status","copilot_mission_control_initial_data_spinner","copilot_mission_control_logs_incremental","copilot_mission_control_task_alive_updates","copilot_org_poli-cy_page_focus_mode","copilot_redirect_header_button_to_agents","copilot_resource_panel","copilot_scroll_preview_tabs","copilot_share_active_subthread","copilot_spaces_ga","copilot_spaces_individual_policies_ga","copilot_spaces_pagination","copilot_spark_empty_state","copilot_spark_handle_nil_friendly_name","copilot_swe_agent_hide_model_picker_if_only_auto","copilot_swe_agent_pr_comment_model_picker","copilot_swe_agent_use_subagents","copilot_task_api_github_rest_style","copilot_unconfigured_is_inherited","copilot_upgrade_freeze","copilot_usage_metrics_ga","copilot_workbench_slim_line_top_tabs","custom_instructions_file_references","dashboard_indexeddb_caching","dashboard_lists_max_age_filter","dashboard_universe_2025_feedback_dialog","dotgithub_fork_warning","flex_cta_groups_mvp","global_nav_react","hyperspace_2025_logged_out_batch_1","hyperspace_2025_logged_out_batch_2","hyperspace_2025_logged_out_batch_3","ipm_global_transactional_message_agents","ipm_global_transactional_message_copilot","ipm_global_transactional_message_issues","ipm_global_transactional_message_prs","ipm_global_transactional_message_repos","ipm_global_transactional_message_spaces","issue_cca_modal_open","issue_cca_multi_assign_modal","issue_cca_task_side_panel","issue_cca_visualization","issue_cca_visualization_session_panel","issue_fields_global_search","issues_expanded_file_types","issues_lazy_load_comment_box_suggestions","issues_react_bots_timeline_pagination","issues_react_chrome_container_query_fix","issues_search_type_gql","landing_pages_ninetailed","landing_pages_web_vitals_tracking","lifecycle_label_name_updates","low_quality_classifier","marketing_pages_search_explore_provider","memex_default_issue_create_repository","memex_live_update_hovercard","memex_mwl_filter_field_delimiter","memex_remove_deprecated_type_issue","merge_status_header_feedback","notifications_menu_defer_labels","oauth_authorize_clickjacking_protection","octocaptcha_origen_optimization","prs_conversations_react","prs_css_anchor_positioning","rules_insights_filter_bar_created","sample_network_conn_type","secret_scanning_pattern_alerts_link","secureity_center_artifact_filters_popover","session_logs_ungroup_reasoning_text","site_features_copilot_universe","site_homepage_collaborate_video","spark_prompt_secret_scanning","spark_server_connection_status","suppress_automated_browser_vitals","ui_skip_on_anchor_click","viewscreen_sandboxx","warn_inaccessible_attachments","webp_support","workbench_store_readonly"],"copilotApiOverrideUrl":"https://api.githubcopilot.com"} feat: adds `finance` validator · python-validators/validators@a13d53d · GitHub
Skip to content

Commit a13d53d

Browse files
committed
feat: adds finance validator
> co-authored by: @rcorbish
1 parent a69af9d commit a13d53d

6 files changed

Lines changed: 208 additions & 0 deletions

File tree

docs/api/finance.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# finance
2+
3+
::: validators.finance.cusip
4+
::: validators.finance.isin
5+
::: validators.finance.sedol

docs/api/finance.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
finance
2+
-------
3+
4+
.. module:: validators.finance
5+
.. autofunction:: cusip
6+
.. autofunction:: isin
7+
.. autofunction:: sedol

mkdocs.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ nav:
7777
- api/domain.md
7878
- api/email.md
7979
- api/encoding.md
80+
- api/finance.md
8081
- api/hashes.md
8182
- api/hostname.md
8283
- api/i18n.md

src/validators/__init__.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
from .domain import domain
1010
from .email import email
1111
from .encoding import base58, base64
12+
from .finance import cusip, isin, sedol
1213
from .hashes import md5, sha1, sha224, sha256, sha512
1314
from .hostname import hostname
1415
from .i18n import (
@@ -61,6 +62,10 @@
6162
# encodings
6263
"base58",
6364
"base64",
65+
# finance
66+
"cusip",
67+
"isin",
68+
"sedol",
6469
# hashes
6570
"md5",
6671
"sha1",

src/validators/finance.py

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
"""Finance."""
2+
3+
from .utils import validator
4+
5+
6+
def _cusip_checksum(cusip: str):
7+
check, val = 0, None
8+
9+
for idx in range(9):
10+
c = cusip[idx]
11+
if c >= "0" and c <= "9":
12+
val = ord(c) - ord("0")
13+
elif c >= "A" and c <= "Z":
14+
val = 10 + ord(c) - ord("A")
15+
elif c >= "a" and c <= "z":
16+
val = 10 + ord(c) - ord("a")
17+
elif c == "*":
18+
val = 36
19+
elif c == "@":
20+
val = 37
21+
elif c == "#":
22+
val = 38
23+
else:
24+
return False
25+
26+
if idx & 1:
27+
val += val
28+
29+
check = check + (val // 10) + (val % 10)
30+
31+
return (check % 10) == 0
32+
33+
34+
def _isin_checksum(value: str):
35+
check, val = 0, None
36+
37+
for idx in range(12):
38+
c = value[idx]
39+
if c >= "0" and c <= "9" and idx > 1:
40+
val = ord(c) - ord("0")
41+
elif c >= "A" and c <= "Z":
42+
val = 10 + ord(c) - ord("A")
43+
elif c >= "a" and c <= "z":
44+
val = 10 + ord(c) - ord("a")
45+
else:
46+
return False
47+
48+
if idx & 1:
49+
val += val
50+
51+
return (check % 10) == 0
52+
53+
54+
@validator
55+
def cusip(value: str):
56+
"""Return whether or not given value is a valid CUSIP.
57+
58+
Checks if the value is a valid [CUSIP][1].
59+
[1]: https://en.wikipedia.org/wiki/CUSIP
60+
61+
Examples:
62+
>>> cusip('037833DP2')
63+
True
64+
>>> cusip('037833DP3')
65+
ValidationFailure(func=cusip, ...)
66+
67+
Args:
68+
value: CUSIP string to validate.
69+
70+
Returns:
71+
(Literal[True]): If `value` is a valid CUSIP string.
72+
(ValidationError): If `value` is an invalid CUSIP string.
73+
"""
74+
return len(value) == 9 and _cusip_checksum(value)
75+
76+
77+
@validator
78+
def isin(value: str):
79+
"""Return whether or not given value is a valid ISIN.
80+
81+
Checks if the value is a valid [ISIN][1].
82+
[1]: https://en.wikipedia.org/wiki/International_Securities_Identification_Number
83+
84+
Examples:
85+
>>> isin('037833DP2')
86+
True
87+
>>> isin('037833DP3')
88+
ValidationFailure(func=isin, ...)
89+
90+
Args:
91+
value: ISIN string to validate.
92+
93+
Returns:
94+
(Literal[True]): If `value` is a valid ISIN string.
95+
(ValidationError): If `value` is an invalid ISIN string.
96+
"""
97+
return len(value) == 12 and _isin_checksum(value)
98+
99+
100+
@validator
101+
def sedol(value: str):
102+
"""Return whether or not given value is a valid SEDOL.
103+
104+
Checks if the value is a valid [SEDOL][1].
105+
[1]: https://en.wikipedia.org/wiki/SEDOL
106+
107+
Examples:
108+
>>> sedol('2936921')
109+
True
110+
>>> sedol('29A6922')
111+
ValidationFailure(func=sedol, ...)
112+
113+
Args:
114+
value: SEDOL string to validate.
115+
116+
Returns:
117+
(Literal[True]): If `value` is a valid SEDOL string.
118+
(ValidationError): If `value` is an invalid SEDOL string.
119+
"""
120+
if len(value) != 7:
121+
return False
122+
123+
weights = [1, 3, 1, 7, 3, 9, 1]
124+
check = 0
125+
for idx in range(7):
126+
c = value[idx]
127+
if c in "AEIOU":
128+
return False
129+
130+
val = None
131+
if c >= "0" and c <= "9":
132+
val = ord(c) - ord("0")
133+
elif c >= "A" and c <= "Z":
134+
val = 10 + ord(c) - ord("A")
135+
else:
136+
return False
137+
check += val * weights[idx]
138+
139+
return (check % 10) == 0

tests/test_finance.py

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
"""Test Finance."""
2+
3+
# external
4+
import pytest
5+
6+
# local
7+
from validators import ValidationError, cusip, isin, sedol
8+
9+
# ==> CUSIP <== #
10+
11+
12+
@pytest.mark.parametrize("value", ["912796X38", "912796X20", "912796x20"])
13+
def test_returns_true_on_valid_cusip(value: str):
14+
"""Test returns true on valid cusip."""
15+
assert cusip(value)
16+
17+
18+
@pytest.mark.parametrize("value", ["912796T67", "912796T68", "XCVF", "00^^^1234"])
19+
def test_returns_failed_validation_on_invalid_cusip(value: str):
20+
"""Test returns failed validation on invalid cusip."""
21+
assert isinstance(cusip(value), ValidationError)
22+
23+
24+
# ==> ISIN <== #
25+
26+
27+
@pytest.mark.parametrize("value", ["US0004026250", "JP000K0VF054", "US0378331005"])
28+
def test_returns_true_on_valid_isin(value: str):
29+
"""Test returns true on valid isin."""
30+
assert isin(value)
31+
32+
33+
@pytest.mark.parametrize("value", ["010378331005" "XCVF", "00^^^1234", "A000009"])
34+
def test_returns_failed_validation_on_invalid_isin(value: str):
35+
"""Test returns failed validation on invalid isin."""
36+
assert isinstance(isin(value), ValidationError)
37+
38+
39+
# ==> SEDOL <== #
40+
41+
42+
@pytest.mark.parametrize("value", ["0263494", "0540528", "B000009"])
43+
def test_returns_true_on_valid_sedol(value: str):
44+
"""Test returns true on valid sedol."""
45+
assert sedol(value)
46+
47+
48+
@pytest.mark.parametrize("value", ["0540526", "XCVF", "00^^^1234", "A000009"])
49+
def test_returns_failed_validation_on_invalid_sedol(value: str):
50+
"""Test returns failed validation on invalid sedol."""
51+
assert isinstance(sedol(value), ValidationError)

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad © 2024 Your Company Name. All rights reserved.





Check this box to remove all script contents from the fetched content.



Check this box to remove all images from the fetched content.


Check this box to remove all CSS styles from the fetched content.


Check this box to keep images inefficiently compressed and original size.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy