Skip to content

Commit

Permalink
Add extra methods for Internet provider
Browse files Browse the repository at this point in the history
  • Loading branch information
lk-geimfari committed Jun 27, 2024
1 parent 5d93322 commit 6807849
Show file tree
Hide file tree
Showing 7 changed files with 146 additions and 7 deletions.
6 changes: 4 additions & 2 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
Version 17.1.0
--------------

- Added ``iata_code()`` method for ``Address`` provider.
- Added ``icao_code()`` method for ``Address`` provider.
- Added the `iata_code()` method for the `Address` provider.
- Added the `icao_code()` method for the `Address` provider.
- Added the `asn` method for the `Internet` provider.
- Added the `special_ip_v4_object()` and `special_ip_v4()` methods for the `Internet` provider, along with the `IPv4Purpose` enum for those methods.

Version 17.0.0
--------------
Expand Down
4 changes: 2 additions & 2 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,9 @@
# built documents.
#
# The short X.Y version.
version = "17.0"
version = "17.1"
# The full version, including alpha/beta/rc tags.
release = "17.0.0"
release = "17.1.0"

# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
Expand Down
4 changes: 3 additions & 1 deletion mimesis/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
FileType,
Gender,
ImageFile,
IPv4Purpose,
ISBNFormat,
MeasureUnit,
MetricPrefixSign,
Expand Down Expand Up @@ -118,6 +119,7 @@
"Gender",
"ImageFile",
"ISBNFormat",
"IPv4Purpose",
"MeasureUnit",
"MetricPrefixSign",
"MimeType",
Expand Down Expand Up @@ -148,7 +150,7 @@
"__license__",
]

__version__ = "17.0.0"
__version__ = "17.1.0"
__title__ = "mimesis"
__description__ = "Mimesis: Fake Data Generator."
__url__ = "https://github.com/lk-geimfari/mimesis"
Expand Down
32 changes: 32 additions & 0 deletions mimesis/enums.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,38 @@
from enum import Enum, auto


class IPv4Purpose(Enum):
"""Provides IPv4 address ranges for different purposes.
An argument for :meth:`~mimesis.Internet.special_ip_v4_object()`.
We use integer representation of IP addresses instead of
IPv4Network objects for better performance.
"""

THIS_NETWORK = (0, 16_777_215)
AMT = (3_224_682_752, 3_224_683_007)
LOOBACK = (2_130_706_432, 2_147_483_647)
AS112_V4 = (3_223_307_264, 3_223_307_519)
LINK_LOCAL = (2_851_995_648, 2_852_061_183)
TEST_NET_1 = (3_221_225_984, 3_221_226_239)
TEST_NET_2 = (3_325_256_704, 3_325_256_959)
TEST_NET_3 = (3_405_803_776, 3_405_804_031)
BENCHMARKING = (3_323_068_416, 3_323_199_487)
PRIVATE_USE_1 = (167_772_160, 184_549_375)
PRIVATE_USE_2 = (2_886_729_728, 2_887_778_303)
PRIVATE_USE_3 = (3_232_235_520, 3_232_301_055)
RESERVED = (4_026_531_840, 4_294_967_295)
SHARE_ADDRESS_SPACE = (1_681_915_904, 1_686_110_207)
LIMITED_BROADCAST = (4_294_967_295, 4_294_967_295)
IPV4_DUMMY_ADDRESS = (3_221_225_480, 3_221_225_480)
TURN_RELAY_ANYCAST = (3_221_225_482, 3_221_225_482)
IETF_PROTOCOL_ASSIGNMENTS = (3_221_225_472, 3_221_225_727)
PORT_CONTROL_PROTOCOL_ANYCAST = (3_221_225_481, 3_221_225_481)
IPV4_SERVICE_CONTINUITY_PREFIX = (3_221_225_472, 3_221_225_479)
DIRECT_DELEGATION_AS112_SERVICE = (3_232_706_560, 3_232_706_815)


class DurationUnit(Enum):
"""Provides duration units.
Expand Down
37 changes: 37 additions & 0 deletions mimesis/providers/internet.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
)
from mimesis.enums import (
DSNType,
IPv4Purpose,
Locale,
MimeType,
PortRange,
Expand Down Expand Up @@ -126,6 +127,9 @@ def http_method(self) -> str:
def ip_v4_object(self) -> IPv4Address:
"""Generates a random :py:class:`ipaddress.IPv4Address` object.
If you only need special purpose IPv4 addresses,
use :meth:`special_ip_v4_object`.
:return: :py:class:`ipaddress.IPv4Address` object.
"""
return IPv4Address(
Expand Down Expand Up @@ -175,6 +179,20 @@ def ip_v6(self) -> str:
"""
return str(self.ip_v6_object())

def asn(self) -> str:
"""Generates a random 4-byte ASN.
ASNs reserved for private use are not considered.
:return: ASN number as a string.
:Example:
AS123456
"""
ranges = (1, 4_199_999_999)
number = self.random.randint(*ranges)
return f"AS{number}"

def mac_address(self) -> str:
"""Generates a random MAC address.
Expand Down Expand Up @@ -516,3 +534,22 @@ def http_request_headers(self) -> dict[str, t.Any]:
),
}
return headers

def special_ip_v4_object(self, purpose: IPv4Purpose | None = None) -> IPv4Address:
"""Generates a special purpose IPv4 address.
:param purpose: Enum object :class:`enums.IPv4Purpose`.
:return: IPv4 address.
:raises NonEnumerableError: if purpose not in :class:`enums.IPv4Purpose`.
"""
ranges = self.validate_enum(purpose, IPv4Purpose)
number = self.random.randint(*ranges)
return IPv4Address(number)

def special_ip_v4(self, purpose: IPv4Purpose | None = None) -> str:
"""Generates a special purpose IPv4 address as string.
:param purpose: Enum object :class:`enums.IPv4Purpose`.
:return: IPv4 address as string.
"""
return str(self.special_ip_v4_object(purpose))
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "mimesis"
version = "17.0.0"
version = "17.1.0"
description = "Mimesis: Fake Data Generator."
authors = ["Isaak Uchakaev <[email protected]>"]
license = "MIT"
Expand Down
68 changes: 67 additions & 1 deletion tests/test_providers/test_internet.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,14 @@
import validators

from mimesis import Internet, datasets
from mimesis.enums import DSNType, MimeType, PortRange, TLDType, URLScheme
from mimesis.enums import (
DSNType,
IPv4Purpose,
MimeType,
PortRange,
TLDType,
URLScheme,
)
from mimesis.exceptions import NonEnumerableError

from . import patterns
Expand Down Expand Up @@ -302,6 +309,54 @@ def test_http_request_headers(self, net):
assert isinstance(result, dict)
assert result["Cookie"].startswith("csrftoken")

def test_asn(self, net):
result = net.asn()
assert isinstance(result, str)
assert result.startswith("AS")
assert 1 <= int(result[2:]) <= 4_199_999_999

@pytest.mark.parametrize(
"purpose",
[
None,
IPv4Purpose.THIS_NETWORK,
IPv4Purpose.AMT,
IPv4Purpose.LOOBACK,
IPv4Purpose.AS112_V4,
IPv4Purpose.LINK_LOCAL,
IPv4Purpose.TEST_NET_1,
IPv4Purpose.TEST_NET_2,
IPv4Purpose.TEST_NET_3,
IPv4Purpose.BENCHMARKING,
IPv4Purpose.PRIVATE_USE_1,
IPv4Purpose.PRIVATE_USE_2,
IPv4Purpose.PRIVATE_USE_3,
IPv4Purpose.RESERVED,
IPv4Purpose.SHARE_ADDRESS_SPACE,
IPv4Purpose.LIMITED_BROADCAST,
IPv4Purpose.IPV4_DUMMY_ADDRESS,
IPv4Purpose.TURN_RELAY_ANYCAST,
IPv4Purpose.IETF_PROTOCOL_ASSIGNMENTS,
IPv4Purpose.PORT_CONTROL_PROTOCOL_ANYCAST,
IPv4Purpose.IPV4_SERVICE_CONTINUITY_PREFIX,
IPv4Purpose.DIRECT_DELEGATION_AS112_SERVICE,
],
)
def test_special_ip_v4_object(self, net, purpose):
ip = net.special_ip_v4_object(purpose)
assert ip.version == 4
assert isinstance(ip, IPv4Address)
if purpose is not None:
assert purpose.value[0] <= int(ip) <= purpose.value[1]

def test_special_ip_v4_object_wrong_arg(self, net):
with pytest.raises(NonEnumerableError):
net.special_ip_v4_object("nil")

def test_special_ip_v4(self, net):
ip = net.special_ip_v4(purpose=None)
assert re.match(patterns.IP_V4_REGEX, ip)


class TestSeededInternet:
@pytest.fixture
Expand Down Expand Up @@ -405,3 +460,14 @@ def test_public_dns(self, i1, i2):

def test_dsn(self, i1, i2):
assert i1.dsn() == i2.dsn()

def test_asn(self, i1, i2):
assert i1.asn() == i2.asn()

def test_special_ip_v4_object(self, i1, i2):
assert i1.special_ip_v4_object(purpose=None) == i2.special_ip_v4_object(
purpose=None
)
assert i1.special_ip_v4_object(purpose=None) == i2.special_ip_v4_object(
purpose=None
)

0 comments on commit 6807849

Please sign in to comment.