Code Monkey home page Code Monkey logo

fantasynames's Introduction

Fantasy Name Generator

PyPI version

A random name generator that produces names aligning (more or less) with common conventions for fantasy characters in fictional media such as Dungeons and Dragons or World of Warcraft.

Installation

python3 -m pip install fantasynames

Or if your project is using Poetry:

poetry add fantasynames

Usage

The following name generating methods are provided for a variety of different stereotypical fantasy "races", as well as a few different "medieval-y" languages:

import fantasynames as names

names.elf()
# Example outputs: 'Farathia Eaviel', 'Iethian Willowblossom'

names.dwarf()
# Example outputs: 'Dagdr Steelbeard', 'Thorinna Ironstrike'

names.hobbit()
# Example outputs: 'Libby Honeyfoot', 'Flublius Sweetscone'

names.french()
# Example outputs: 'Richert Roublac', 'Clavena de Clardalle'

names.anglo()
# Example outputs: 'Brandin of Avonlyn', 'Kallem Davenmere'

names.human()
# Example outputs: 'Danric du Tourbloc', 'Sumia Sageholme'

Note that human() provides a diverse mix of different first and last name styles, including anglo() and french()...and more!

You can also pass a string argument to specify whether you want to recieve masculine or feminine names. By default, it's totally random:

names.human() # this will randomly generate either a male or female name

names.human('any') # this is equivalent to the above, in case you want to be specific

names.human('male') # this will generate a masculine name

names.human('female') # this will generate a feminine name

Contributing

Poetry

This package uses Poetry for package management. After checking out the repo, use poetry install to install all the required dependencies. Anytime you need to add a package, use:

poetry add PACKAGE_NAME_HERE

Continuous Integration Tests

We do code formatting with Python Black, additional linting with flake8, and type checking with mypy. Before opening a PR, please make sure to run all of these. Below is a helpful command to do them all at once:

poetry run black fantasynames && poetry run flake8 fantasynames && poetry run mypy fantasynames

We also run some tests with pytest:

poetry run pytest

Guides

If you want to make your own name generators, check out:

And then if you want to ramp up the complexity, take a look at:

fantasynames's People

Contributors

jessica-px avatar leov1963 avatar wballard avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar

fantasynames's Issues

Rename 'human_data' to 'anglo_data'

Originally, the language now known in the codebase as 'anglo' was called 'human'...and I missed a few spots when I renamed it. 'human_data' in data.py needs to be renamed to anglo_data, but also do a search to see if there are other places where it looks like it should be 'anglo' instead. human_diverse.py is probably(?) the only place where we should do anything involving "humans". If something looks sus to you, just add it to the PR description.

Missing License

This project appears to be missing a license which makes it hard to determine when and how it can be used.

Convert data.py to json

It'll be easier to reuse the data in data.py if we store it in json instead of Python. Change this to a .json file, do any re-formatting necessary, and make sure files that need to read from it can still do so successfully.

Add orc name generator

Orcs are a pretty big fantasy race that we're totally neglecting. It'd be nice to include them. Make sure to follow the steps in both of these guides:

Here's some good inspiration for orc names:

Just off the bat I'm imagining something like:

col1 col2
RAG AG*
MAR Ash
zAG nAth
GrAG dArm

Where the transformations are:
R = r or l
A = a, o, or u
G = k or g
M = m or n

This should give names like Nurosh, Kragnuth, and Logakk*, which I think sound pretty orc-y. Please add a few more options than this though, and consider surnames as well. Tweak it until you think you get a good proportion of usable names. And don't forget to add it to the readme!

*(The * character was not included in the readme guide -- read the comments in the _transform() method and the double_consonant() function to learn more about it. And if you're feeling philanthropical, you can add it to the guide yourself).

Allow options for just first/last name

The Problem

Right now we only make one method accessible: name(), and it always returns a string with a first and last name combined. But what if our users only want one name? It'd be crappy to expect them to just split the string, especially because names like Jane of Doeville have more than one white space in them. We should be able to send 'Jane' and 'of Doeville' separately. Users should be able to choose whether they want a first name, last name, or full name.

A tricky thing

We already have one string keyword argument (also called a "named" argument or "optional" argument) on this method. We allow users to customize the gender of their name with this keyword argument, but in our documentation, we sort of make it look like a positional argument. Once we have multiple keyword arguments, this will get confusing, so we'll have to update our documentation to be more explicit.

For more info on keyword vs positional arguments, watch this video.

The goal of this ticket

Let's add a new keyword argument to the name() method on the Language class for selecting whether it returns a first name, last name, or full name. We'll call this argument type and it can accept the strings 'first', 'last', or 'full'. By default, it should equal 'full'.

So, calling fantasynames.dwarf() should still return a full name of a random gender, but calling fantasynames.dwarf(gender='female', type='first') should return a feminine first name.

Then we should update README.md to document how to use this function. We should also update the documentation for the gender argument to explicitly show the keyword, so we don't confuse anyone into thinking these are positional arguments.

Add validators

The Problem

Some name combinations turn out weird. Like maybe Willowbloom and Nightwhisper came out fine, but then Willowwhisper is...yeah. Those double w's just don't work.

Or like, in the elf language, I like seeing y used as a vowel...unless it's at the beginning of a name. Elnyra looks great, but how am I supposed to read Ylnera?? I don't like it.

Or! We have Willard and Arland -- fine. But what happens when Will gets paired with land? That's right -- Willland. Absolutely hateful.

The Solution

So let's add a validation step to our name generators. After doing their transformations, we'll make them go through a series of checks and toss out any names that don't work. Of course, if a name gets rejected, we'll have to generate new ones until we find a valid one. So a while loop might be appropriate.

So we'll want to add some kind of validator to the Language class, which will probably read from a list of "invalid substrings" that we don't want to see in any of our names. Like this:

@classmethod
def _is_name_valid(name: string) -> bool:
   invalid_substrings = ["ww"]
   # check if the given name contains any of these substrings

And then in our name generating logic, we'll want to upgrade our name() method so it contains a while loop where we keep generating names until one of them passes this test. Like this:

@classmethod
    def name(cls, gender: str = "any") -> str:
        name_is_valid = false
        while !name_is_valid:
            name = # this is where the existing name-generating logic goes
            name_is_valid = validate_name(name)
        else:
            return name

This might or might not actually work, it's a rough brain dump.

Scope of this Ticket

For starters, let's just add a validator banning ww and lll in the Language class.

To ensure it works, we should add a test for it -- this should have its own file tests and can simply run the _is_name_valid method on a dummy language. We would want to run a test for both a true and false example. This can be based on the existing special_rules_test.py.

Add pytest

Testing randomly generated names will be weird, but if we can get some basic tests in place to prove that our functions don't crash, we can add that to some CI. Which would make auto-publishing to PyPi a lot less risky.

Some ideas for testing:

  • Run each generating function once, make sure they don't crash
  • Make sure the outputs have exactly two capital letters (this might need changing if we get weirder with the names)
  • Run a transformation with exactly one possible result, make sure the end string matches that result

Test each name generating method

Add a new test file in tests named names_test.py or something. The goal of this file is to import each of the name generating methods listed in __init__.py and make sure that they successfully return strings with a length greater than zero. We're not going to test them more thoroughly than that, but this test will be useful because it will alert us if we accidentally break one of these methods somehow.

installation problem with typed-ast package

Hi,
I ran into an installation problem with pip install fantasynames.

I created a new virtual env which uses python 3.10.4 and the following packages:

pip 22.1.2
setuptools 62.4.0
wheel 0.37.1

I am running this on macOS 12.1.

When I try to install fantasynames I get the following output which indicates that there is a problem with building typed-ast 1.4.3
output.txt

I can however install typed-ast 1.5.4 without a problem. I tried to install the dependencies individually to narrow the search a little bit down and it seems like mypy0.812 wants to use typed-ast 1.4.3 which does not build on my machine for reasons I don't know.
So I looked into the issue page of typed-ast and besides that the support for typed-ast will end soon I found this:

"I ran into the same thing, I'm seeing this issue pop up on CI for python 3.10.1 on Windows 10 and Mac OSX, without any code changes to my repo. typed-ast 1.4.3 trying to build from source, and building fails for those two configurations. Python 3.7-3.9 work fine, and Ubuntu works fine.

Here's a representative run which was passing about a month ago, but failing now: https://github.com/scottshambaugh/monaco/runs/4847920477?check_suite_focus=true

Edit: This was resolved by unpinning my mypy version from 0.800. More recent versions of mypy removed typed-ast as a dependency."

python/typed_ast#183

This is where my little programming/detective skills came to an end. Seems like the installation enforces mypy 0.800 which enforces typed-ast 1.4.3 which doesn't work for python 3.10 on windows or mac. Of course I could try now just using python 3.9 but I would rather not downgrade my python version because fantasynames is not the only package I want to use. Is there any way for me how to solve this issue on another way?

Thank you in advance :)

Add genders

Problem

Realistically most people would probably like control over whether they're generating a masculine or feminine name. But how do we determine masculinity/femininity for randomized names? Like sure, distinguishing Robert and Roberta is easy, but what about Ann and Ryan? Or more modern unisex names like Robin and Alex?? We cannot programmatically predict gender of real English names with absolute certainty, so we'll have to pick some metric for determining gender that is far more limited and artificial than our reality, but still recognizable to English speakers.

Proposal

So the idea is that a "feminine" name for the Anglo, French, or Hobbit languages must have one of the following suffixes:
-a, -ia, -y, -ie, -e, -is, -ise, -isa, -ette, or -etta

Note that some of these like -y might profit from some consonant transformations (Pen -> Penny instead of Peny). I mean, what -y actually needs is two preceding consonants, but idk if we actually want to get that explicit with the rule...

For the Elf language, we'll draw a little from Gaelic:
-a, -ia, -yn, -in, -ail, -eal, -i

For the Dwarf language we'll draw from various Nordic languages and a dash of Gaelic I guess:
-a, -ig, -aid, -ssi, -ja, -is, -et
Depending on how "feminine" these sound to our Anglophone ears, we might or might not have to tweak these.

Masculine names in most Indo-European languages go "un-suffixed", because masculinity is the default etc etc patriarchy. But we could throw in a few masculine suffixes like -o or -us if we want.

Implementation

Let's give every name generating function an optional string parameter for selecting the gender. Even if that language doesn't have gender, we should let it return a random name instead of throwing an error (because that might surprise people).

import fantasynames as names

names.anglo()      # will return any name (either 'Jon' or 'Jona')
names.anglo('any')    # equivalent to above (either 'Jon' or 'Jona'), just here in case people want to be explicit
names.anglo('male')      # In most cases will probably just generate a suffix-less name ('Jon')
names.anglo('female')      # will return a name with a feminine suffix ('Jona')


names.snake()       # will return any name
names.snake('female')    # this (fake) language doesn't actually have gender, but it will just return a random name instead of throwing an error

Testing

Once we have pytest, we should add tests ensuring that every name-generating language returns something when given 'male', 'female', or 'any' as an argument, or when given no arguments. It should throw a helpful error if anything else is passed.

Add half-elf name generator

This one should be fairly straightforward -- we want a new name generator that draws from our existing human names and elf names, and randomly mixes them up.

It might be fun to force some diversity here -- if we left it completely random, some of the names would end up purely human or purely elven. Maybe it's a 50/50 chance to get human first name + elf surname VS elf first name + human surname. Because otherwise, what's half-elven about the name, right?

Add goblin name generator

Goblins might not be popular player characters, but they are fun. Let's add a generator that adds silly names like Glubbik Snagglegrin and Deekz Mudbaby or something. Purely fantastical names like Beegus Grig'ukul are also valid.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.