-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
9c42aba
commit 8a26a65
Showing
7 changed files
with
204 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
name: CI | ||
on: pull_request | ||
|
||
jobs: | ||
ci: | ||
strategy: | ||
fail-fast: false | ||
matrix: | ||
python-version: [3.9] | ||
os: [ubuntu-latest] | ||
runs-on: ${{ matrix.os }} | ||
steps: | ||
- uses: actions/checkout@v2 | ||
- uses: actions/setup-python@v2 | ||
with: | ||
python-version: ${{ matrix.python-version }} | ||
- name: Install Poetry | ||
run: | | ||
curl -sSL https://raw.githubusercontent.com/python-poetry/poetry/master/get-poetry.py | python | ||
- name: Add path for Poetry | ||
run: echo "$HOME/.poetry/bin" >> $GITHUB_PATH | ||
- name: Install Dependencies | ||
run: poetry install --no-interaction | ||
- name: Run tests | ||
run: poetry run pytest |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,42 @@ | ||
# netcleanser | ||
# netcleanser | ||
|
||
The library makes parsing and manipulation of URL🌐 and Email address📧 easy. | ||
|
||
![ci](https://github.com/y-bar/netcleanser/workflows/ci/badge.svg?branch=master) | ||
[![license](https://img.shields.io/github/license/y-bar/netcleanser.svg)](https://github.com/y-bar/netcleanser/blob/master/LICENSE) | ||
[![release](https://img.shields.io/github/release/y-bar/netcleanser.svg)](https://github.com/y-bar/netcleanser/releases/latest) | ||
|
||
|
||
## Install | ||
|
||
```bash | ||
pip install netcleanser | ||
``` | ||
|
||
## How to use | ||
|
||
|
||
```python | ||
>>> from netcleanser import Email | ||
>>> email = Email('[email protected]') | ||
>>> email.domain | ||
'gmail.com' | ||
>>> email.local_part | ||
'shinichi.takayanagi' | ||
>>> email.is_valid() | ||
True | ||
>>> email.value | ||
'[email protected]' | ||
``` | ||
|
||
This `Email` class is `settable` and `dictable` | ||
```python | ||
# As dict | ||
>>> x = {email: 1} | ||
>>> x[email] | ||
1 | ||
# As set | ||
>>> {Email.build(), email, email, email} | ||
{Email(value='[email protected])', Email(value='[email protected])'} | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
from netcleanser.email import Email |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
import re | ||
from typing import Optional, Final | ||
|
||
# Thanks! | ||
# https://gist.github.com/neu5ron/66078f804f16f9bda828 | ||
DOMAIN_NAME_REGEX: Final[str] = re.compile(r'(([\da-zA-Z])([_\w-]{,62})\.){,127}(([\da-zA-Z])[_\w-]{,61})?([\da-zA-Z]\.((xn\-\-[a-zA-Z\d]+)|([a-zA-Z\d]{2,})))', re.IGNORECASE) | ||
|
||
def _looks_domain(x: str) -> bool: | ||
domain_name = x.lower().strip().encode('ascii') | ||
return True if re.match(DOMAIN_NAME_REGEX, x) else False | ||
|
||
def _automatic_correction(email: str) -> str: | ||
return email.replace("@", "@") | ||
|
||
class Email: | ||
def __init__(self, value: Optional[str] = None): | ||
self._set_to_none() | ||
if value is None: | ||
return | ||
try: | ||
self._value = _automatic_correction(value) | ||
self._local_part, self._domain = self._value.split('@') | ||
except: | ||
if _looks_domain(value): | ||
self._local_part = "" | ||
self._domain = value | ||
self._value = f"@{self._domain}" | ||
else: | ||
self._set_to_none() | ||
|
||
def _set_to_none(self): | ||
self._value = None | ||
self._local_part = None | ||
self._domain = None | ||
|
||
def __str__(self): | ||
return self._value | ||
|
||
def __repr__(self): | ||
# The same format with dataclass ;) | ||
return f"Email(value='{self._value})'" | ||
|
||
def __eq__(self, other): | ||
if not isinstance(other, Email): | ||
return False | ||
return self._value == other._value | ||
|
||
def __hash__(self): | ||
return hash(self._value) | ||
|
||
def is_valid(self) -> bool: | ||
return (self._value is not None) | ||
|
||
@property | ||
def domain(self) -> str: | ||
return self._domain | ||
|
||
@property | ||
def value(self) -> str: | ||
return self._value | ||
|
||
@property | ||
def local_part(self) -> str: | ||
return self._local_part | ||
|
||
@staticmethod | ||
def build(local_part: str = "dummy", domain: str = "dummy.com"): | ||
return Email(f"{local_part}@{domain}") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
[tool.poetry] | ||
name = "netcleanser" | ||
version = "0.1.0" | ||
description = "The library makes parsing and manipulation of URL🌐 and Email address📧 easy." | ||
authors = ["Shinichi Takayanagi <[email protected]>", "Nakamura Michihiro <[email protected]>"] | ||
license = "MIT" | ||
|
||
[tool.poetry.dependencies] | ||
python = "^3.9" | ||
|
||
[tool.poetry.dev-dependencies] | ||
pytest = "^6.2.4" | ||
|
||
[build-system] | ||
requires = ["poetry-core>=1.0.0"] | ||
build-backend = "poetry.core.masonry.api" |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
from netcleanser import Email | ||
|
||
|
||
def test_email(): | ||
for value in ["[email protected]", "hoge.moge@gmail.com"]: | ||
email = Email(value) | ||
assert email.is_valid() == True | ||
assert email.local_part == "hoge.moge" | ||
assert email.domain == "gmail.com" | ||
assert str(email) == email.value | ||
assert Email.build(email.local_part, email.domain) == email | ||
|
||
def test_empty_local_part(): | ||
for value in ["gmail.com", "@gmail.com"]: | ||
email = Email(value) | ||
assert email.is_valid() == True | ||
assert email.local_part == "" | ||
assert email.domain == "gmail.com" | ||
assert str(email) == email.value | ||
assert Email.build(email.local_part, email.domain) == email | ||
|
||
def test_internationalized_domain(): | ||
for value in ["あうふへぇ@ほげほげ.com", "あうふへぇ@ほげほげ.com"]: | ||
email = Email(value) | ||
assert email.is_valid() == True | ||
assert email.local_part == "あうふへぇ" | ||
assert email.domain == "ほげほげ.com" | ||
assert str(email) == email.value | ||
assert Email.build(email.local_part, email.domain) == email | ||
|
||
def test_email_is_invalid(): | ||
for value in ["", "akdsjfkjh", None]: | ||
email = Email(value) | ||
assert email.is_valid() == False | ||
assert email.local_part is None | ||
assert email.domain is None | ||
assert email.value is None | ||
|
||
def test_email_build(): | ||
email = Email().build(domain="hoge.com") | ||
assert email.local_part == "dummy" | ||
assert email.domain == "hoge.com" | ||
|
||
email = Email.build(local_part="hoge") | ||
assert email.local_part == "hoge" | ||
assert email.domain == "dummy.com" | ||
|
||
def test_email_should_be_settable(): | ||
{Email("[email protected]"), Email("xxx@yahooo")} | ||
|
||
def test_email_should_be_dictable(): | ||
{Email("[email protected]"): 123, Email("xxx@yahooo"): 456} |