Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update dictionary files from upstream #214

Merged
merged 7 commits into from
Feb 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions CHANGELOG.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,40 @@
[discrete]
=== Breaking Change

* https://github.com/serpro69/kotlin-faker/pull/214[#214] [core] Update `Faker#internet#domain` function which affects returned values
* https://github.com/serpro69/kotlin-faker/pull/213[#213] [core] Add support for unique data generation to `Faker#random`

[discrete]
=== Added

* https://github.com/serpro69/kotlin-faker/pull/214[#214] [core] Update dictionary files, including:
** Data and functions in existing data providers
** `Faker().internet.domain()` now takes optional argument and produces a "safe-domain" (ending with `.example` or `.test`)
** Updates to existing localized dictionaries + one new locale
* https://github.com/serpro69/kotlin-faker/issues/208[#208] [core] Allow `StringProvider#regexify` to take Regex as input
* https://github.com/serpro69/kotlin-faker/pull/202[#202] [core] Allow `randomClassInstance` to directly use predefined generators

++++
<details><summary><h3>New Data Providers</h3></summary>
<p>
++++
* `smashing_pumpkins`
* `the_room`
++++
</p>
</details>
++++

++++
<details><summary><h3>New Locales</h3></summary>
<p>
++++
* `en-KE`
++++
</p>
</details>
++++

[discrete]
=== Changed

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,11 @@ fun renderProvider(
it.callBy(mapOf(it.parameters[0] to instance)).toString()
} else it.call(instance, "").toString()
}
3 -> it.call(instance, "", "").toString()
3 -> {
if (it.parameters[1].isOptional && it.parameters[2].isOptional) {
it.callBy(mapOf(it.parameters[0] to instance)).toString()
} else it.call(instance, "", "").toString()
}
else -> {
when (it) {
Money::amount -> it.call(provider.getter.call(faker), 100_000..1_000_000, true, ",", ".")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -678,6 +678,10 @@
"name": "getSlackEmoji",
"parameterTypes": []
},
{
"name": "getSmashingPumpkins",
"parameterTypes": []
},
{
"name": "getSonicTheHedgehog",
"parameterTypes": []
Expand Down Expand Up @@ -782,6 +786,10 @@
"name": "getTheOffice",
"parameterTypes": []
},
{
"name": "getTheRoom",
"parameterTypes": []
},
{
"name": "getTheThickOfIt",
"parameterTypes": []
Expand Down Expand Up @@ -4616,6 +4624,27 @@
}
]
},
{
"name": "io.github.serpro69.kfaker.provider.SmashingPumpkins",
"methods": [
{
"name": "musicians",
"parameterTypes": []
},
{
"name": "albums",
"parameterTypes": []
},
{
"name": "lyric",
"parameterTypes": []
},
{
"name": "songs",
"parameterTypes": []
}
]
},
{
"name": "io.github.serpro69.kfaker.provider.SonicTheHedgehog",
"methods": [
Expand Down Expand Up @@ -5274,6 +5303,27 @@
}
]
},
{
"name": "io.github.serpro69.kfaker.provider.TheRoom",
"methods": [
{
"name": "actors",
"parameterTypes": []
},
{
"name": "characters",
"parameterTypes": []
},
{
"name": "locations",
"parameterTypes": []
},
{
"name": "quotes",
"parameterTypes": []
}
]
},
{
"name": "io.github.serpro69.kfaker.provider.TheThickOfIt",
"methods": [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,7 @@ class IntrospectorTest : DescribeSpec() {
"SiliconValley",
"Simpsons",
"SlackEmoji",
"SmashingPumpkins",
"SonicTheHedgehog",
"SouthPark",
"Space",
Expand All @@ -214,6 +215,7 @@ class IntrospectorTest : DescribeSpec() {
"TheITCrowd",
"TheKingkillerChronicle",
"TheOffice",
"TheRoom",
"TheThickOfIt",
"Tolkien",
"Touhou",
Expand Down Expand Up @@ -410,6 +412,7 @@ class IntrospectorTest : DescribeSpec() {
"siliconValley",
"simpsons",
"slackEmoji",
"smashingPumpkins",
"sonicTheHedgehog",
"southPark",
"space",
Expand All @@ -436,6 +439,7 @@ class IntrospectorTest : DescribeSpec() {
"theITCrowd",
"theKingkillerChronicle",
"theOffice",
"theRoom",
"theThickOfIt",
"tolkien",
"touhou",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,11 @@ class FakerIT : DescribeSpec({
it.callBy(mapOf(it.parameters[0] to provider.getter.call(faker))).toString()
} else it.call(provider.getter.call(faker), "").toString()
}
3 -> it.call(provider.getter.call(faker), "", "").toString()
3 -> {
if (it.parameters[1].isOptional && it.parameters[2].isOptional) {
it.callBy(mapOf(it.parameters[0] to provider.getter.call(faker))).toString()
} else it.call(provider.getter.call(faker), "", "").toString()
}
else -> throw IllegalArgumentException("")
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,22 +1,42 @@
package io.github.serpro69.kfaker.provider

import io.github.serpro69.kfaker.Faker
import io.github.serpro69.kfaker.faker
import io.kotest.assertions.assertSoftly
import io.kotest.core.spec.style.DescribeSpec
import io.kotest.matchers.collections.shouldHaveSize
import io.kotest.matchers.shouldBe
import io.kotest.matchers.string.shouldEndWith
import io.kotest.matchers.string.shouldMatch
import io.kotest.matchers.string.shouldNotContain
import io.kotest.matchers.string.shouldStartWith

@Suppress("unused")
class InternetIT : DescribeSpec({
describe("Internet provider") {
val faker = Faker()
val ukFaker = faker { fakerConfig { locale = "uk" } }
val internet = faker.internet

// https://stackoverflow.com/a/201378/5917497
val emailRegex = Regex("""
(?:[a-z0-9!#${'$'}%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#${'$'}%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9]))\.){3}(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9])|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])
""".trimIndent())

context("generates a domain name") {
internet.domain() shouldMatch Regex("""[a-z]+(-[a-z]+)?\.(example|test)""")
internet.domain(subdomain = true).split(".") shouldHaveSize 3
internet.domain(subdomain = true) shouldMatch Regex("""[a-z]+(-[a-z]+)?\.[a-z]+(-[a-z]+)?\.(example|test)""")
internet.domain(domain = "foo") shouldStartWith "foo"
internet.domain(subdomain = true, domain = "bar").split(".")[1] shouldBe "bar"
internet.domain(domain = "kotlin-faker.test") shouldBe "kotlin-faker.test"
internet.domain(subdomain = true, domain = "kotlin-faker.test").substringAfter(".") shouldBe "kotlin-faker.test"
internet.domain(subdomain = true, domain = "faker.kotlin-faker.test") shouldBe "faker.kotlin-faker.test"
// check domain normalization from Ukrainian lang
ukFaker.internet.domain() shouldMatch Regex("""[a-z]+(-[a-z]+)?\.(example|test)""")
ukFaker.internet.domain(subdomain = true) shouldMatch Regex("""[a-z]+(-[a-z]+)?\.[a-z]+(-[a-z]+)?\.(example|test)""")
}

context("generates an email address") {
val emails = List(1000) { internet.email() }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ class PhoneNumberIT : DescribeSpec({
phone.cellPhone.number() shouldMatch Regex("""^\(\d{3}\) \d{3}-\d{2}-\d{2}$""")
}
it("country code is resolved using default format") {
phone.countryCode.code() shouldBeIn defaultCountryCodes
phone.countryCode() shouldBeIn defaultCountryCodes
}
}

Expand All @@ -34,14 +34,14 @@ class PhoneNumberIT : DescribeSpec({
phone.cellPhone.number() shouldContain Regex("""^0[987]0""")
}
it("country code is resolved using default format") {
phone.countryCode.code() shouldBeIn defaultCountryCodes
phone.countryCode() shouldBeIn defaultCountryCodes
}
}

context("fr") {
val phone = phoneNumber("fr")
it("country code is resolved using default format") {
phone.countryCode.code() shouldBe "33"
phone.countryCode() shouldBe "33"
}
}

Expand All @@ -54,7 +54,9 @@ class PhoneNumberIT : DescribeSpec({
it("should generate a cellPhone.number run#$it") {
phone.cellPhone.number().filter { c -> c.isDigit() } shouldNotBe ""
}
it("should generate a countryCode.code run#$it") {
it("should generate a countryCode run#$it") {
phone.countryCode() shouldNotBe ""
// test deprecated function until it's removed
phone.countryCode.code() shouldNotBe ""
}
}
Expand Down
2 changes: 2 additions & 0 deletions core/src/main/kotlin/io/github/serpro69/kfaker/Faker.kt
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,7 @@ class Faker @JvmOverloads constructor(internal val config: FakerConfig = fakerCo
val siliconValley: SiliconValley by lazy { SiliconValley(fakerService) }
val simpsons: Simpsons by lazy { Simpsons(fakerService) }
val slackEmoji: SlackEmoji by lazy { SlackEmoji(fakerService) }
val smashingPumpkins: SmashingPumpkins by lazy { SmashingPumpkins(fakerService) }
val sonicTheHedgehog: SonicTheHedgehog by lazy { SonicTheHedgehog(fakerService) }

// val source: Source by lazy {Source(fakerService }
Expand Down Expand Up @@ -232,6 +233,7 @@ class Faker @JvmOverloads constructor(internal val config: FakerConfig = fakerCo
val theITCrowd: TheITCrowd by lazy { TheITCrowd(fakerService) }
val theKingkillerChronicle: TheKingkillerChronicle by lazy { TheKingkillerChronicle(fakerService) }
val theOffice: TheOffice by lazy { TheOffice(fakerService) }
val theRoom: TheRoom by lazy { TheRoom(fakerService) }
val theThickOfIt: TheThickOfIt by lazy { TheThickOfIt(fakerService) }
val tolkien: Tolkien by lazy { Tolkien(fakerService) }
val touhou: Touhou by lazy { Touhou(fakerService) }
Expand Down
41 changes: 24 additions & 17 deletions core/src/main/kotlin/io/github/serpro69/kfaker/FakerService.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import io.github.serpro69.kfaker.dictionary.Dictionary
import io.github.serpro69.kfaker.dictionary.RawExpression
import io.github.serpro69.kfaker.dictionary.YamlCategory
import io.github.serpro69.kfaker.dictionary.YamlCategory.CELL_PHONE
import io.github.serpro69.kfaker.dictionary.YamlCategory.COUNTRY_CODE
import io.github.serpro69.kfaker.dictionary.YamlCategory.CURRENCY_SYMBOL
import io.github.serpro69.kfaker.dictionary.YamlCategory.PHONE_NUMBER
import io.github.serpro69.kfaker.dictionary.YamlCategory.SEPARATOR
Expand Down Expand Up @@ -152,23 +151,18 @@ internal class FakerService {
return dictionary
}

private fun computePhoneNumber(category: YamlCategory): Any {
return computePhoneNumber(category, "en") as Any
private fun computePhoneNumber(category: YamlCategory): HashMap<String, Any>? {
return computePhoneNumber(category, "en")
}

private fun computePhoneNumber(category: YamlCategory, locale: String): Any? {
private fun computePhoneNumber(category: YamlCategory, locale: String): HashMap<String, Any>? {
val instr = when (locale) {
"en", "ja", "fr" -> getCategoryFileStream(locale, PHONE_NUMBER, null)
else -> getLocaleFileStream(locale)
}
return instr?.use {
when (category) {
PHONE_NUMBER, CELL_PHONE -> readCategoryOrNull(it, locale, category)
COUNTRY_CODE -> {
val localeData = Mapper.readValue(it, Map::class.java)[locale] as Map<*, *>
val fakerData = localeData["faker"] as Map<*, *>
fakerData[category.lowercase()]
}
PHONE_NUMBER, CELL_PHONE -> readCategoryOrNull(it, locale, category) as HashMap?
else -> null
}
}
Expand All @@ -194,20 +188,33 @@ internal class FakerService {
*
* @throws IllegalArgumentException if the [locale] is invalid or locale dictionary file is not present on the classpath.
*/
@Suppress("UNCHECKED_CAST", "UNUSED_ANONYMOUS_PARAMETER")
@Suppress("UNUSED_ANONYMOUS_PARAMETER")
internal fun load(category: YamlCategory, secondaryCategory: Category? = null): Dictionary {
val defaultValues: LinkedHashMap<String, Any> = linkedMapOf()

dictionary.compute(category) { _, categoryData -> // i.e. compute data for 'address' category
// TODO can this be improved by doing smth along the lines of categoryData.computeIfAbsent()
when (category) {
PHONE_NUMBER, CELL_PHONE -> {
computePhoneNumber(category, locale)?.let { defaultValues.putAll(it as Map<out String, Any>) }
?: defaultValues.putAll(computePhoneNumber(category) as Map<String, Any>)
/* Some keys are missing in localized phone.yml files,
* e.g. compare locales/en/phone.yml with locales/fr/phone.yml or locales/ja/phone.yml.
* So we merge the 'en/phone' keys with localized ones
* to avoid "Parameter '...' not found in 'phone_number' category" exceptions
*
* NB! We also needed to split-out handling of CELL_PHONE category into own branch
* because otherwise it would get merged with PHONE_NUMBER, and we would get
* "Parameter '...' not found in 'cell_phone' category" exceptions
*/
PHONE_NUMBER -> {
computePhoneNumber(category, locale)?.let { localePhones ->
computePhoneNumber(category)?.let { enPhones ->
enPhones.forEach { (k, v) -> localePhones.computeIfAbsent(k) { v } }
}
defaultValues.putAll(localePhones)
}
}
COUNTRY_CODE -> {
computePhoneNumber(category, locale)?.let { defaultValues[category.lowercase()] = it }
?: run { defaultValues[category.lowercase()] = computePhoneNumber(category) }
CELL_PHONE -> {
computePhoneNumber(category, locale)?.let { defaultValues.putAll(it) }
?: computePhoneNumber(category)?.let { defaultValues.putAll(it) }
}
SEPARATOR, CURRENCY_SYMBOL -> {
computeSymbol(category, locale)?.let {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,6 @@ internal enum class YamlCategory : Category {
CONSTRUCTION,
COSMERE,
COWBOY_BEBOP,
COUNTRY_CODE,
CREATURE,
CROSSFIT,
CRYPTO_COIN,
Expand Down Expand Up @@ -161,6 +160,7 @@ internal enum class YamlCategory : Category {
SHOW,
SILICON_VALLEY,
SIMPSONS,
SMASHING_PUMPKINS,
SLACK_EMOJI,
SOURCE,
SOUTH_PARK,
Expand All @@ -185,6 +185,7 @@ internal enum class YamlCategory : Category {
FRESH_PRINCE_OF_BEL_AIR,
THE_IT_CROWD,
THE_OFFICE,
THE_ROOM,
THE_THICK_OF_IT,
TOLKIEN,
TRAIN_STATION,
Expand Down
Loading
Loading