From c3612c3bfcc91abc0ea44cb9e45c8d837d63121a Mon Sep 17 00:00:00 2001 From: Paul Prescod Date: Fri, 11 Jun 2021 15:28:10 -0700 Subject: [PATCH 01/53] Improve coverage --- docs/salesforce.md | 5 +- .../cci_mapping_files/post_processes.py | 8 +- snowfakery/data_generator.py | 2 +- tests/test_collections.py | 155 ++++++++++++++++++ tests/test_generate_mapping.py | 19 +++ tests/test_output_streams.py | 8 + 6 files changed, 192 insertions(+), 5 deletions(-) create mode 100644 tests/test_collections.py diff --git a/docs/salesforce.md b/docs/salesforce.md index ff64ff77..85681e80 100644 --- a/docs/salesforce.md +++ b/docs/salesforce.md @@ -58,7 +58,7 @@ been added in a previous CumulusCI task or some other process. For example, if you have a Campaign object and would like to associate Contacts to it through CampaignMembers. -Here is an example were we query a particular Campaign object: +Here is an example where we query a particular Campaign object: ```yaml # examples/salesforce/CampaignMembers-first.recipe.yml @@ -222,6 +222,9 @@ like this: $ snowfakery recipe.yml --plugin-options orgname qa ``` +When you run the recipe in this way, it will connect to the org to pull data but +not change data in the org at all. + ## Record Types To specify a Record Type for a record, just put the Record Type’s API Name in a field named RecordType. diff --git a/snowfakery/cci_mapping_files/post_processes.py b/snowfakery/cci_mapping_files/post_processes.py index 7609d41e..9725a82d 100644 --- a/snowfakery/cci_mapping_files/post_processes.py +++ b/snowfakery/cci_mapping_files/post_processes.py @@ -2,6 +2,8 @@ def add_after_statements(mappings): + """Automatically add CCI after: statements to the lookups + in a mapping file""" indexed_by_sobject = _index_by_sobject(mappings) for idx, (mapping_name, mapping) in enumerate(mappings.items()): @@ -16,9 +18,9 @@ def add_after_statements(mappings): lookup["after"] = target_mapping_index.last_step_name -class MappingIndex(NamedTuple): - first_instance: int - last_step_name: str +class MappingIndex(NamedTuple): # info needed by the algorithm above + first_instance: int # where was the first time this sobj was referenced? + last_step_name: str # where was the last (so far)? def _index_by_sobject(mappings): diff --git a/snowfakery/data_generator.py b/snowfakery/data_generator.py index 468a692c..60f7e6d9 100644 --- a/snowfakery/data_generator.py +++ b/snowfakery/data_generator.py @@ -193,7 +193,7 @@ def process_plugins_options( """Replace option short names with fully qualified names and convert types of options. e.g. the option name that the user specifies on the CLI or API is just "orgname" - but we use the long name internally to aavoid clashing with the + but we use the long name internally to avoid clashing with the user's variable names.""" allowed_options = collect_allowed_plugin_options(tuple(plugins.values())) diff --git a/tests/test_collections.py b/tests/test_collections.py new file mode 100644 index 00000000..b312ae36 --- /dev/null +++ b/tests/test_collections.py @@ -0,0 +1,155 @@ +from snowfakery.utils.collections import CaseInsensitiveDict +import pytest + + +# From: https://github.com/psf/requests/blob/05a1a21593c9c8e79393d35fae12c9c27a6f7605/tests/test_requests.py +class TestCaseInsensitiveDict: + @pytest.mark.parametrize( + "cid", + ( + CaseInsensitiveDict({"Foo": "foo", "BAr": "bar"}), + CaseInsensitiveDict([("Foo", "foo"), ("BAr", "bar")]), + CaseInsensitiveDict(FOO="foo", BAr="bar"), + ), + ) + def test_init(self, cid): + assert len(cid) == 2 + assert "foo" in cid + assert "bar" in cid + + def test_docstring_example(self): + cid = CaseInsensitiveDict() + cid["Accept"] = "application/json" + assert cid["aCCEPT"] == "application/json" + assert list(cid) == ["Accept"] + + def test_len(self): + cid = CaseInsensitiveDict({"a": "a", "b": "b"}) + cid["A"] = "a" + assert len(cid) == 2 + + def test_getitem(self): + cid = CaseInsensitiveDict({"Spam": "blueval"}) + assert cid["spam"] == "blueval" + assert cid["SPAM"] == "blueval" + + def test_fixes_649(self): + """__setitem__ should behave case-insensitively.""" + cid = CaseInsensitiveDict() + cid["spam"] = "oneval" + cid["Spam"] = "twoval" + cid["sPAM"] = "redval" + cid["SPAM"] = "blueval" + assert cid["spam"] == "blueval" + assert cid["SPAM"] == "blueval" + assert list(cid.keys()) == ["SPAM"] + + def test_delitem(self): + cid = CaseInsensitiveDict() + cid["Spam"] = "someval" + del cid["sPam"] + assert "spam" not in cid + assert len(cid) == 0 + + def test_contains(self): + cid = CaseInsensitiveDict() + cid["Spam"] = "someval" + assert "Spam" in cid + assert "spam" in cid + assert "SPAM" in cid + assert "sPam" in cid + assert "notspam" not in cid + + def test_get(self): + cid = CaseInsensitiveDict() + cid["spam"] = "oneval" + cid["SPAM"] = "blueval" + assert cid.get("spam") == "blueval" + assert cid.get("SPAM") == "blueval" + assert cid.get("sPam") == "blueval" + assert cid.get("notspam", "default") == "default" + + def test_update(self): + cid = CaseInsensitiveDict() + cid["spam"] = "blueval" + cid.update({"sPam": "notblueval"}) + assert cid["spam"] == "notblueval" + cid = CaseInsensitiveDict({"Foo": "foo", "BAr": "bar"}) + cid.update({"fOO": "anotherfoo", "bAR": "anotherbar"}) + assert len(cid) == 2 + assert cid["foo"] == "anotherfoo" + assert cid["bar"] == "anotherbar" + + def test_update_retains_unchanged(self): + cid = CaseInsensitiveDict({"foo": "foo", "bar": "bar"}) + cid.update({"foo": "newfoo"}) + assert cid["bar"] == "bar" + + def test_iter(self): + cid = CaseInsensitiveDict({"Spam": "spam", "Eggs": "eggs"}) + keys = frozenset(["Spam", "Eggs"]) + assert frozenset(iter(cid)) == keys + + def test_equality(self): + cid = CaseInsensitiveDict({"SPAM": "blueval", "Eggs": "redval"}) + othercid = CaseInsensitiveDict({"spam": "blueval", "eggs": "redval"}) + assert cid == othercid + del othercid["spam"] + assert cid != othercid + assert cid == {"spam": "blueval", "eggs": "redval"} + assert cid != object() + + def test_setdefault(self): + cid = CaseInsensitiveDict({"Spam": "blueval"}) + assert cid.setdefault("spam", "notblueval") == "blueval" + assert cid.setdefault("notspam", "notblueval") == "notblueval" + + def test_lower_items(self): + cid = CaseInsensitiveDict( + { + "Accept": "application/json", + "user-Agent": "requests", + } + ) + keyset = frozenset(lowerkey for lowerkey, v in cid.lower_items()) + lowerkeyset = frozenset(["accept", "user-agent"]) + assert keyset == lowerkeyset + + def test_preserve_key_case(self): + cid = CaseInsensitiveDict( + { + "Accept": "application/json", + "user-Agent": "requests", + } + ) + keyset = frozenset(["Accept", "user-Agent"]) + assert frozenset(i[0] for i in cid.items()) == keyset + assert frozenset(cid.keys()) == keyset + assert frozenset(cid) == keyset + + def test_preserve_last_key_case(self): + cid = CaseInsensitiveDict( + { + "Accept": "application/json", + "user-Agent": "requests", + } + ) + cid.update({"ACCEPT": "application/json"}) + cid["USER-AGENT"] = "requests" + keyset = frozenset(["ACCEPT", "USER-AGENT"]) + assert frozenset(i[0] for i in cid.items()) == keyset + assert frozenset(cid.keys()) == keyset + assert frozenset(cid) == keyset + + def test_copy(self): + cid = CaseInsensitiveDict( + { + "Accept": "application/json", + "user-Agent": "requests", + } + ) + cid_copy = cid.copy() + assert str(cid) == str(cid_copy) + assert cid == cid_copy + cid["changed"] = True + assert cid != cid_copy diff --git a/tests/test_generate_mapping.py b/tests/test_generate_mapping.py index b4927bf1..8c03524f 100644 --- a/tests/test_generate_mapping.py +++ b/tests/test_generate_mapping.py @@ -10,6 +10,7 @@ _table_is_free, ) from snowfakery.data_generator_runtime import Dependency +from snowfakery.cci_mapping_files.post_processes import add_after_statements from snowfakery import data_gen_exceptions as exc @@ -285,6 +286,24 @@ def test_incomplete_record_types(self, tmpdir, generate_in_tmpdir): assert mapping["Insert Case"]["fields"]["RecordTypeId"] == "recordtype" +class TestAddAfterStatements: + def test_add_after_statements(self): + mappings = { + "Insert Child": { + "fields": {}, + "lookups": {"parent": {"key_field": "parent", "table": "Parent"}}, + "sf_object": "Child", + "table": "Child", + }, + "Insert Parent": {"fields": {}, "sf_object": "Parent", "table": "Parent"}, + "Insert Parent 2": {"fields": {}, "sf_object": "Parent", "table": "Parent"}, + } + add_after_statements(mappings) + assert ( + mappings["Insert Child"]["lookups"]["parent"]["after"] == "Insert Parent 2" + ) + + class TestPersonAccounts: def test_basic_person_accounts(self, generate_in_tmpdir): recipe_data = """ diff --git a/tests/test_output_streams.py b/tests/test_output_streams.py index e4d1b9d0..b4b0b313 100644 --- a/tests/test_output_streams.py +++ b/tests/test_output_streams.py @@ -10,6 +10,8 @@ import pytest +from click.exceptions import ClickException + from sqlalchemy import create_engine from snowfakery.output_streams import ( @@ -367,3 +369,9 @@ def test_external_output_stream_yaml(self): """ print(x.getvalue()) assert x.getvalue() == expected + + def test_external_output_stream__failure(self): + with pytest.raises(ClickException, match="no.such.output.Stream"): + generate_cli.callback( + yaml_file=sample_yaml, output_format="no.such.output.Stream" + ) From 42e85293c6988fa3fb806107018f4576bff4c96a Mon Sep 17 00:00:00 2001 From: Paul Prescod Date: Fri, 11 Jun 2021 16:19:38 -0700 Subject: [PATCH 02/53] More text coverage --- snowfakery/data_gen_exceptions.py | 2 +- snowfakery/data_generator.py | 2 +- snowfakery/object_rows.py | 6 +----- tests/test_cli.py | 25 ++++++++++++++++++++++-- tests/test_faker.py | 12 ++++++++++++ tests/test_with_cci.py | 32 +++++++++++++++++++++---------- 6 files changed, 60 insertions(+), 19 deletions(-) diff --git a/snowfakery/data_gen_exceptions.py b/snowfakery/data_gen_exceptions.py index e064d3db..ff685cc8 100644 --- a/snowfakery/data_gen_exceptions.py +++ b/snowfakery/data_gen_exceptions.py @@ -15,7 +15,7 @@ def __init__(self, message, filename=None, line_num=None): def __str__(self): if self.line_num: location = f"\n near {self.filename}:{self.line_num}" - elif self.filename: + elif self.filename: # pragma: no cover location = f"\n in {self.filename}" else: location = "" diff --git a/snowfakery/data_generator.py b/snowfakery/data_generator.py index 60f7e6d9..983cac58 100644 --- a/snowfakery/data_generator.py +++ b/snowfakery/data_generator.py @@ -40,7 +40,7 @@ def __init__(self, parse_results, runtime_results): self.templates = parse_results.templates self.intertable_dependencies = runtime_results.intertable_dependencies - def summarize_for_debugging(self): + def summarize_for_debugging(self): # pragma: no cover return self.intertable_dependencies, self.templates diff --git a/snowfakery/object_rows.py b/snowfakery/object_rows.py index 574ebd53..87ad5f62 100644 --- a/snowfakery/object_rows.py +++ b/snowfakery/object_rows.py @@ -49,10 +49,6 @@ def __setstate__(self, state): for slot, value in state.items(): setattr(self, slot, value) - @property - def _name(self): - return self._values.get("name") - class ObjectReference(yaml.YAMLObject): def __init__(self, tablename, id): @@ -104,5 +100,5 @@ def status(self): elif self.allocated_id == SlotState.CONSUMED: return SlotState.CONSUMED - def __repr__(self): + def __repr__(self): # pragma: no cover return f"" diff --git a/tests/test_cli.py b/tests/test_cli.py index 29e9d217..185e3370 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -9,7 +9,7 @@ from tests.utils import named_temporary_file_path import yaml -from click.exceptions import ClickException +from click.exceptions import ClickException, BadParameter from snowfakery.cli import generate_cli, eval_arg, main from snowfakery.data_gen_exceptions import DataGenError @@ -179,6 +179,13 @@ def test_from_cli__target_number(self, capsys): assert len(re.findall(r"Account\(", stdout)) == 5 + def test_from_cli__bad_target_number(self): + with pytest.raises(BadParameter): + generate_cli.main( + [str(sample_yaml), "--target-number", "abc", "def"], + standalone_mode=False, + ) + def test_from_cli__explicit_format_txt(self, capsys): with named_temporary_file_path() as t: generate_cli.main( @@ -198,7 +205,7 @@ def test_from_cli__explicit_format_txt(self, capsys): output = f.read() assert len(re.findall(r"Account\(", output)) == 5 - def test_from_cli__unknown_extension(self, capsys): + def test_from_cli__unknown_format(self, capsys): with pytest.raises(ClickException) as e: generate_cli.callback( yaml_file=str(sample_yaml), @@ -209,6 +216,20 @@ def test_from_cli__unknown_extension(self, capsys): assert "xyzzy" in str(e.value) Path("foo.txt").unlink() + def test_from_cli__pluggable_output_stream(self): + with named_temporary_file_path(suffix=".yml") as t: + generate_cli.main( + [ + str(sample_yaml), + "--output-format", + "examples.YamlOutputStream", + "--output-file", + t, + ], + standalone_mode=False, + ) + assert t.exists() + def test_from_cli__continuation(self, capsys): with TemporaryDirectory() as t: mapping_file_path = Path(t) / "mapping.yml" diff --git a/tests/test_faker.py b/tests/test_faker.py index af959ea9..3caf6157 100644 --- a/tests/test_faker.py +++ b/tests/test_faker.py @@ -207,6 +207,18 @@ def test_error_handling(self, write_row_mock): assert "xyzzy" in str(e.value) assert "fake" in str(e.value) + @mock.patch(write_row_path) + def test_did_you_mean(self, write_row_mock): + yaml = """ + - object: A + fields: + xyzzy: + fake: frst_name + """ + with pytest.raises(exc.DataGenError) as e: + generate(StringIO(yaml), {}, None) + assert "first_name" in str(e.value) + def test_faker_internals_are_invisible(self): yaml = """ - object: A diff --git a/tests/test_with_cci.py b/tests/test_with_cci.py index 2a67bea7..6d14efca 100644 --- a/tests/test_with_cci.py +++ b/tests/test_with_cci.py @@ -71,12 +71,12 @@ def query(self, query: str): ) +@patch( + "snowfakery.standard_plugins.Salesforce.SalesforceConnection.sf", + wraps=fake_sf_client, +) +@patch("snowfakery.standard_plugins.Salesforce.randrange", lambda *arg, **kwargs: 5) class TestSOQLNoCCI: - @patch( - "snowfakery.standard_plugins.Salesforce.SalesforceConnection.sf", - wraps=fake_sf_client, - ) - @patch("snowfakery.standard_plugins.Salesforce.randrange", lambda *arg, **kwargs: 5) def test_soql_plugin_random(self, fake_sf_client, generated_rows): yaml = """ - plugin: snowfakery.standard_plugins.Salesforce.SalesforceQuery @@ -91,11 +91,6 @@ def test_soql_plugin_random(self, fake_sf_client, generated_rows): assert fake_sf_client.mock_calls assert generated_rows.row_values(0, "AccountId") == "FAKEID5" - @patch( - "snowfakery.standard_plugins.Salesforce.SalesforceConnection.sf", - wraps=fake_sf_client, - ) - @patch("snowfakery.standard_plugins.Salesforce.randrange", lambda *arg, **kwargs: 5) def test_soql_plugin_record(self, fake_sf_client, generated_rows): yaml = """ - plugin: snowfakery.standard_plugins.Salesforce.SalesforceQuery @@ -110,6 +105,23 @@ def test_soql_plugin_record(self, fake_sf_client, generated_rows): assert fake_sf_client.mock_calls assert generated_rows.row_values(0, "AccountId") == "FAKEID0" + def test_soql_plugin_random__orgname_long(self, fake_sf_client, generated_rows): + yaml = """ + - plugin: snowfakery.standard_plugins.Salesforce.SalesforceQuery + - object: Contact + fields: + FirstName: Suzy + LastName: Salesforce + AccountId: + SalesforceQuery.random_record: Account + """ + plugin_option_name = ( + "snowfakery.standard_plugins.Salesforce.SalesforceQuery.orgname" + ) + generate(StringIO(yaml), plugin_options={plugin_option_name: "blah"}) + assert fake_sf_client.mock_calls + assert generated_rows.row_values(0, "AccountId") == "FAKEID5" + class TestSOQLWithCCI: @patch("snowfakery.standard_plugins.Salesforce.randrange", lambda *arg, **kwargs: 0) From 31139e53c1edbe3b08aa54feaef1a8f8ee465484 Mon Sep 17 00:00:00 2001 From: Paul Prescod Date: Fri, 11 Jun 2021 17:22:14 -0700 Subject: [PATCH 03/53] Snowfakery 2 --- HISTORY.md | 13 +++++++++++++ snowfakery/version.txt | 2 +- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/HISTORY.md b/HISTORY.md index 9296a6f5..f50a949c 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -4,6 +4,19 @@ In the beginning, programmers created the databases. Now the databases were form And so [Salesforce.org](http://salesforce.org/) said “Let there be data,” and there was Snowfakery. And it was good. +## Snowfakery 2.0 + +Recipes can now merge in data from Salesforce. (#395) + +Output streams can now be specified as 3rd party libraries. Any Python classname +can be passed to --output-format as long as it adheres to the OutputStream +protocol as shown in examples/YamlOutputStream.py (#351) + +Snowfakery is thread-safe/multi-processor-ready and available for parallel usage +in CumulusCI. (CumulusCI Repo) + +Snowfakery now supports a more intuitive and properly documented fake list. (TBD) + ## Snowfakery 1.12 Fix a regression: In some contexts it was impossible to call Faker with either diff --git a/snowfakery/version.txt b/snowfakery/version.txt index 35d51f33..415b19fc 100644 --- a/snowfakery/version.txt +++ b/snowfakery/version.txt @@ -1 +1 @@ -1.12 \ No newline at end of file +2.0 \ No newline at end of file From f3847d93f41e8093db26ae455773e649d23ef4ec Mon Sep 17 00:00:00 2001 From: Paul Prescod Date: Sun, 13 Jun 2021 12:54:00 -0700 Subject: [PATCH 04/53] Doc gen infrastructure --- .gitignore | 1 + CONTRIBUTING.rst | 24 ++ Makefile | 3 + docs/Makefile | 20 -- docs/conf.py | 3 +- docs/index.md | 313 ++++++++---------- mkdocs.yml | 14 + requirements/dev.in | 3 +- requirements/dev.txt | 82 +++-- requirements/prod.txt | 34 +- setup.py | 3 +- .../docs/examples/secret_life_of_pets.yml | 2 +- snowfakery/fakedata/fake_data_generator.py | 35 +- snowfakery/tools/mkdocs.py | 24 ++ tools/faker_docs.py | 12 + tools/faker_docs_utils/docs_config.yml | 29 ++ tools/faker_docs_utils/docstring.py | 246 ++++++++++++++ tools/faker_docs_utils/faker_markdown.py | 134 ++++++++ tools/faker_docs_utils/format_samples.py | 152 +++++++++ .../mkdocs_plugins/main_mkdocs_plugin.py | 38 +++ tools/faker_docs_utils/summarize_fakers.py | 65 ++++ tools/faker_docs_utils/validator.py | 154 +++++++++ 22 files changed, 1138 insertions(+), 253 deletions(-) delete mode 100644 docs/Makefile create mode 100644 snowfakery/tools/mkdocs.py create mode 100644 tools/faker_docs.py create mode 100644 tools/faker_docs_utils/docs_config.yml create mode 100644 tools/faker_docs_utils/docstring.py create mode 100644 tools/faker_docs_utils/faker_markdown.py create mode 100644 tools/faker_docs_utils/format_samples.py create mode 100644 tools/faker_docs_utils/mkdocs_plugins/main_mkdocs_plugin.py create mode 100644 tools/faker_docs_utils/summarize_fakers.py create mode 100644 tools/faker_docs_utils/validator.py diff --git a/.gitignore b/.gitignore index 3623a5fc..b8c2bc1c 100644 --- a/.gitignore +++ b/.gitignore @@ -13,6 +13,7 @@ build/ dist/ docs/api/ docs/_build/ +docs/fakedata .eggs/ .idea/ .tox/ diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index 8ff90d9d..89e85458 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -123,3 +123,27 @@ You can finish up the process by updating the release object that was auto-creat Just paste in the changelog notes and hit publish. Tada! You've published a new version of Snowfakery. + +Internal Software Architecture +------------------------------ + +=================================== ================================ +Filename Purpose +----------------------------------- -------------------------------- + +cli.py Click-based Command Line. Uses the Click library to supply a CLI. +data_generator.py The API entry point the CLI and CCI use.

This may be the best place to start reading. It abstracts away all of the complexity and outlines the core flow. +parse_recipe_yaml.py Phase 1: parse YAML into a Runtime DOM

Includes some hacks to the YAML parser for handling line numbers. +data_generator_runtime.py Phase 2: Runtime.

Actually generate the data by walking the template list top-to-bottom, generating rows as appopriate. +data_generator_runtime_dom.py An object model used in Phase 2. Roughly similar to the shape of the YAML file. +output_streams.py Where the data goes in the output. Used during Phase 2. +data_gen_exceptions.py Exceptions that can be thrown +generate_mapping_from_recipe.py In the CCI context, this utility package allows the generation of mapping.yml files. +template_funcs.py Functions that can be invoked using either block syntax or in Jinja templates +plugins.py Infrastructure for plugins +standard_plugins/ Plugins that ship with Snowfakery +tests/ Unit tests +=================================== ================================ + + +Architecture Diagram diff --git a/Makefile b/Makefile index ddeb5f3e..b5e5b282 100644 --- a/Makefile +++ b/Makefile @@ -4,3 +4,6 @@ update-deps: dev-install: pip-sync requirements/*.txt + +doc: + python -m mkdocs build --clean --site-dir build/html --config-file mkdocs.yml diff --git a/docs/Makefile b/docs/Makefile deleted file mode 100644 index 43276bb9..00000000 --- a/docs/Makefile +++ /dev/null @@ -1,20 +0,0 @@ -# Minimal makefile for Sphinx documentation -# - -# You can set these variables from the command line, and also -# from the environment for the first two. -SPHINXOPTS ?= -SPHINXBUILD ?= sphinx-build -SOURCEDIR = . -BUILDDIR = ../build - -# Put it first so that "make" without argument is like "make help". -help: - @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) - -.PHONY: help Makefile - -# Catch-all target: route all unknown targets to Sphinx using the new -# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). -%: Makefile - @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) diff --git a/docs/conf.py b/docs/conf.py index 396cb091..23c008f7 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -27,8 +27,7 @@ # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. -extensions = ["myst_parser"] -myst_config = {} +extensions = [] # Add any paths that contain templates here, relative to this directory. templates_path = ["_templates"] diff --git a/docs/index.md b/docs/index.md index b1293ba1..8c9e9248 100644 --- a/docs/index.md +++ b/docs/index.md @@ -119,7 +119,7 @@ pet_stories.yml - object: Animal fields: name: - fake: first_name + fake: FirstName species: canine food: - object: PetFood @@ -131,7 +131,7 @@ pet_stories.yml - object: Animal fields: name: - fake: first_name + fake: FirstName species: feline food: - object: PetFood @@ -224,6 +224,49 @@ persons_of_interest.yml In this case, there will be 6 Persons in the Person table (or file), 3 with age between 0 and 12 and 3 with age between 12 and 95. +### Fake Data + +You can generate many kinds of fake data using the `fake` function: + +```yaml +- object: Account + fields: + Name: + fake: Company + Description: + fake: CatchPhrase + BillingStreet: + fake: StreetAddress + BillingCity: + fake: City + BillingState: + fake: State +``` + +You can fake all sorts of stuff. Names, addresses, Latin text, English sentences, URLs, etc. + +The complete list is in [it's own document](fakedata.md) + +For example, you can fake a user account like this: + +```yaml +# examples/salesforce/simple-user.yml +- object: User + fields: + Username: + fake: Username + FirstName: + fake: FirstName + LastName: + fake: LastName + Email: + fake: Email + Alias: + fake: Alias +``` + +It doesn't matter if you use upper or lower case for fake names. + ### Friends Sometimes you want to obey a rule like “For every Person I create, I’d like to create 2 animals” (maybe you really like animals). @@ -245,7 +288,7 @@ You would use the `friends` property to do that. count: 2 fields: name: - fake: first_name + fake: FirstName ``` This will output two animals per person: @@ -282,7 +325,7 @@ Relationships are a big part of what makes Snowfakery different than the dozens( - object: Animal fields: name: - fake: first_name + fake: FirstName species: Petaurus Breviceps ``` @@ -313,7 +356,7 @@ In addition, we can relate pets and owners “bidirectionally”, like this: - object: Animal fields: name: - fake: first_name + fake: FirstName owner: reference: Person ``` @@ -366,7 +409,7 @@ pet_stories_2.yml owner: reference: Person name: - fake: first_name + fake: FirstName species: canine food: reference: petschoice @@ -376,7 +419,7 @@ pet_stories_2.yml fields: owner: Person name: - fake: first_name + fake: FirstName species: feline nemesis: dog food: @@ -415,7 +458,7 @@ This function allows you to look up another row (object) and make a reference to - object: Animal fields: name: - fake: first_name + fake: FirstName owner: reference: Person ``` @@ -533,76 +576,7 @@ github issue. ### `fake` -Generate fake data using functions from the [faker](https://github.com/joke2k/faker) library: - -```yaml -- object: Account - fields: - Name: - fake: company - Description: - fake: catch_phrase - BillingStreet: - fake: street_address - BillingCity: - fake: city - BillingState: - fake: state -``` - -You can fake all sorts of stuff. Names, addresses, Latin text, English sentences, URLs, etc. There are two lists of fake names you can pull from, a Snowfakery-specific list, -and the broader faker list. - -The Snowfakery names are: - -- Username: a globally unique username in the shape of an email address - -- Alias: a short string that looks like a first name. - -- FirstName, LastName: Localized first and last name - -- Email: An email address using one of the standard "example" domains (such as example.com, example.org, etc.) - -- RealisticMaybeRealEmail: An email address which looks -more real (because it uses domains like google.com, -yahoo.com, etc.) and may accidentally actually overlap -with a real email address. Be careful using this if -you might send actual emails to the addresses! - -For example, you can use these like this: - -```yaml -# examples/salesforce/simple-user.yml -- object: User - fields: - Username: - fake: Username - FirstName: - fake: FirstName - LastName: - fake: LastName - Email: - fake: Email - Alias: - fake: Alias -``` - -It doesn't matter if you use upper or lower case for fake names. - -The complete list is here: - - - -You can also include Faker extension libraries after you’ve added them to your Python install: - -```yaml - - plugin: faker_microservice.Provider - - object: OBJ - fields: - service_name: - fake: - microservice -``` +FIXME: You would install that provider like this: @@ -619,13 +593,25 @@ And you could make your own providers as well. Fake can be called as an inline function in an expression: ```yaml -FullName: ${{fake.first_name}} Johnson +FullName: ${{fake.FirstName}} Johnson ``` You can also call these functions with arguments as described in Faker's [documentation](https://faker.readthedocs.io/en/master/providers.html) ```yaml -country: ${{fake.country_code(representation='alpha-2')}} +- object: Example + field: + country: ${{fake.country_code(representation='alpha-2')}} +``` + +Or: + +```yaml +- object: Example + field: + country: + fake.country_code: + representation: 'alpha-2' ``` ### International Fakes @@ -761,16 +747,16 @@ some_number: A number ${{random_number(min=5, max=10)}} - choice: when: ${{gender=='Male'}} pick: - fake: first_name_male + fake: FirstNameMale - choice: when: ${{gender=='Female'}} pick: - fake: first_name_female + fake: FirstNameFemale - choice: pick: - fake: first_name + fake: FirstNameNonBinary ``` The `when` clause can be a Python formula and it will be interpreted as a boolean similar to how Python would do it. The first `when` clause that matches is selected. The last `choice` clause should have no `when` clause, and it is a fallback which is selected if the others do not match. @@ -853,17 +839,17 @@ this: ```yaml - var: lastname_var value: - fake: last_name + fake: LastName - object: person fields: - first_name: - fake: first_name - last_name: ${{lastname_var}} + FirstName: + fake: FirstName + LastName: ${{lastname_var}} - object: spouse fields: - first_name: - fake: first_name - last_name: ${{lastname_var}} + FirstName: + fake: FirstName + LastName: ${{lastname_var}} ``` This works both at the top level of your recipe and in friends @@ -878,7 +864,7 @@ do that by creating a "hidden" object: - object: __shared_address fields: street: - fake: street_address + fake: StreetAddress city: fake: city state: @@ -932,7 +918,7 @@ There is a lot to say about formulas and one day they will all be documented her - use `${{` to start a formula and `}}` to end it - use Python expression syntax in the middle - field values defined earlier on this object are available as names -- Use faker values like this: Name: ${{fake.first_name}} Johnson +- Use faker values like this: Name: ${{fake.FirstName}} Johnson - parent (or ancestor) values are available through the parent’s object name. Like Opportunity.amount Formulas are based on a similar language called Jinja2, but we use `${{` and `}}` where Jinja2 uses `{{` and `}}` because our version is more compatible with YAML. @@ -961,7 +947,7 @@ The `id` variable returns a unique identifier for the current Object/Row to allo ```yaml fields: - name: ${{fake.last_name}} Household ${{id}} + name: ${{fake.LastName}} Household ${{id}} ``` #### `today` @@ -1388,6 +1374,66 @@ generate_data( Detailed information is available in [Embedding Snowfakery into Python Applications](./embedding.md) +### Using Snowfakery with Databases + +Snowfakery is built on top of a very flexible engine called +SQLAlchemy. This allows it to connect to many different databases +subject to the limitations described below. + +You should start by installing Snowfakery in a context which +makes it easy to use the Python command 'pip' to manage your +Python environment. For example you could install Python +using the standard installers from `python.org` and then +you would run the following commands to create and use a venv with the +Postgres package: + +```bash + +# create a new directory for our experiment +$ mkdir experiment_with_postgres +# cd into it +$ cd experiment_with_postgres +# create a new database: +# https://www.postgresql.org/docs/9.1/app-createdb.html +$ createdb snowfakerydb +# create a virtual environment. A good habit to get into. +# https://docs.python.org/3/library/venv.html +$ python3 -m venv myvenv +# activate the venv +$ source myvenv/bin/activate +# install Snowfakery in this venv +$ pip install snowfakery +# install the Postgres library for Python +# https://pypi.org/project/psycopg2/ +$ pip install psycopg2 +# let's use it! +$ snowfakery --dburl='postgresql://localhost:5432/snowfakerydb' ~/code/Snowfakery/examples/company.yml --target-number 1000 Employee +# and check the results +# https://www.postgresql.org/docs/9.3/app-psql.html +$ echo 'select * from "Employee"' | psql snowfakerydb +``` + +That's a lot to take in, but hopefully it will be clear enough +to follow the links and understand the details. + +A limitation of this process is that currently Snowfakery can +only create new tables rather than import into existing ones. + +The table will have an id column in addition to columns for every field that +was generated by the recipe. All columns will be of type text. + +The list of databases supported by our underlying infrastructure +(SQLAlchemy) is listed [here](https://docs.sqlalchemy.org/en/14/core/engines.html#supported-databases) and [here](https://docs.sqlalchemy.org/en/13/dialects/index.html). + +Snowfakery is not proactively tested with all of the output +databases. We will certainly accept bug reports and pull requests +relating to problems that are discovered. + +Please keep in touch with the Snowfakery team about your use of +other databases so we can have a sense of what works well and what +does not. + + ## Plugins and Providers Plugins and Providers allow Snowfakery to be extended with Python code. A plugin adds new functions to Snowfakery. A Provider adds new capabilities to the Faker library which is exposed to Snowfakery users through the fake: keyword. @@ -1526,9 +1572,9 @@ CumulusCI can also be used to download CSV data for enrichment as follows. Dataset.shuffle: dataset: ../../accounts.csv FirstName: - fake: first_name + fake: FirstName LastName: - fake: last_name + fake: LastName AccountId: ${{__accounts.Id}} ``` @@ -1655,65 +1701,6 @@ There are several examples [in the Snowfakery repository](https://github.com/SFD Salesforce-specific patterns and tools are described in [Using Snowfakery with Salesforce](salesforce.md) -## Using Snowfakery with Databases - -Snowfakery is built on top of a very flexible engine called -SQLAlchemy. This allows it to connect to many different databases -subject to the limitations described below. - -You should start by installing Snowfakery in a context which -makes it easy to use the Python command 'pip' to manage your -Python environment. For example you could install Python -using the standard installers from `python.org` and then -you would run the following commands to create and use a venv with the -Postgres package: - -```bash - -# create a new directory for our experiment -$ mkdir experiment_with_postgres -# cd into it -$ cd experiment_with_postgres -# create a new database: -# https://www.postgresql.org/docs/9.1/app-createdb.html -$ createdb snowfakerydb -# create a virtual environment. A good habit to get into. -# https://docs.python.org/3/library/venv.html -$ python3 -m venv myvenv -# activate the venv -$ source myvenv/bin/activate -# install Snowfakery in this venv -$ pip install snowfakery -# install the Postgres library for Python -# https://pypi.org/project/psycopg2/ -$ pip install psycopg2 -# let's use it! -$ snowfakery --dburl='postgresql://localhost:5432/snowfakerydb' ~/code/Snowfakery/examples/company.yml --target-number 1000 Employee -# and check the results -# https://www.postgresql.org/docs/9.3/app-psql.html -$ echo 'select * from "Employee"' | psql snowfakerydb -``` - -That's a lot to take in, but hopefully it will be clear enough -to follow the links and understand the details. - -A limitation of this process is that currently Snowfakery can -only create new tables rather than import into existing ones. - -The table will have an id column in addition to columns for every field that -was generated by the recipe. All columns will be of type text. - -The list of databases supported by our underlying infrastructure -(SQLAlchemy) is listed [here](https://docs.sqlalchemy.org/en/14/core/engines.html#supported-databases) and [here](https://docs.sqlalchemy.org/en/13/dialects/index.html). - -Snowfakery is not proactively tested with all of the output -databases. We will certainly accept bug reports and pull requests -relating to problems that are discovered. - -Please keep in touch with the Snowfakery team about your use of -other databases so we can have a sense of what works well and what -does not. - ## Snowfakery Glossary - Object: When we think about our Rows in the context of each other, we often use the word “Object”. That’s because rows often *represent* real-world entities like houses (or at least their, addresses), organizations and people (in this case its acceptable to objectify people). See also: “Rows” @@ -1732,24 +1719,6 @@ call Python methods. It would be unwise to run untrusted recipes in an environment that has access to secure resources such as passwords, network connections, etc. -## Internal Software Architecture - -|Filename |Purpose | -|--- |--- | -|cli.py |Click-based Command Line. Uses the Click library to supply a CLI. | -|data_generator.py |The API entry point the CLI and CCI use.

This may be the best place to start reading. It abstracts away all of the complexity and outlines the core flow. | -|parse_recipe_yaml.py |Phase 1: parse YAML into a Runtime DOM

Includes some hacks to the YAML parser for handling line numbers. | -|data_generator_runtime.py |Phase 2: Runtime.

Actually generate the data by walking the template list top-to-bottom, generating rows as appopriate. -|data_generator_runtime_dom.py |An object model used in Phase 2. Roughly similar to the shape of the YAML file.| -|output_streams.py |Where the data goes in the output. Used during Phase 2. | -|data_gen_exceptions.py |Exceptions that can be thrown | -|generate_mapping_from_recipe.py |In the CCI context, this utility package allows the generation of mapping.yml files. | -|template_funcs.py |Functions that can be invoked using either block syntax or in Jinja templates | -|plugins.py |Infrastructure for plugins | -|standard_plugins/ |Plugins that ship with Snowfakery | -|tests/ |Unit tests | - -Architecture Diagram ## Appendix: The Age Old Puzzle diff --git a/mkdocs.yml b/mkdocs.yml index 35ac1e9a..caebea71 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -1,3 +1,17 @@ site_name: Snowfakery documentation +site_url: "" theme: readthedocs repo_url: https://github.com/SFDO-Tooling/Snowfakery/ +nav: + - index.md + - salesforce.md + - fakedata.md + - embedding.md + - extending.md +markdown_extensions: + - toc: + permalink: True + toc_depth: 4 +plugins: + - search + - snowfakery_fakes # this causes a timeout on ReadTheDocs.org diff --git a/requirements/dev.in b/requirements/dev.in index 9eb9c2b7..a962bac6 100644 --- a/requirements/dev.in +++ b/requirements/dev.in @@ -3,7 +3,8 @@ black coverage coveralls flake8 -myst-parser +# myst-parser # is this actually needed??? +mkdocs pip-tools pre-commit pytest diff --git a/requirements/dev.txt b/requirements/dev.txt index c3158da2..72d74b07 100644 --- a/requirements/dev.txt +++ b/requirements/dev.txt @@ -14,19 +14,17 @@ appdirs==1.4.4 # fs # virtualenv attrs==21.2.0 - # via - # markdown-it-py - # pytest -authlib==0.15.3 + # via pytest +authlib==0.15.4 # via # -r requirements/prod.txt # cumulusci # simple-salesforce babel==2.9.1 # via sphinx -black==21.5b2 +black==21.6b0 # via -r requirements/dev.in -certifi==2020.12.5 +certifi==2021.5.30 # via # -r requirements/prod.txt # cumulusci @@ -48,6 +46,7 @@ click==7.1.2 # -r requirements/prod.txt # black # cumulusci + # mkdocs # pip-tools # snowfakery coloredlogs==15.0 @@ -69,8 +68,13 @@ cryptography==3.4.7 # authlib # cumulusci # jwcrypto -cumulusci==3.36.0 +cumulusci==3.37.0 # via -r requirements/prod.txt +deprecated==1.2.12 + # via + # -r requirements/prod.txt + # cumulusci + # jwcrypto distlib==0.3.2 # via virtualenv docopt==0.6.2 @@ -79,11 +83,10 @@ docutils==0.16 # via # -r requirements/prod.txt # cumulusci - # myst-parser # sphinx faker-microservice==2.0.0 # via -r requirements/dev.in -faker==8.2.1 +faker==8.6.0 # via # -r requirements/prod.txt # cumulusci @@ -99,6 +102,8 @@ fs==2.4.13 # via # -r requirements/prod.txt # cumulusci +ghp-import==2.0.1 + # via mkdocs github3.py==2.0.0 # via # -r requirements/prod.txt @@ -118,7 +123,7 @@ humanfriendly==9.1 # -r requirements/prod.txt # coloredlogs # cumulusci -identify==2.2.7 +identify==2.2.10 # via pre-commit idna==2.10 # via @@ -132,12 +137,14 @@ immutables==0.15 # via # -r requirements/prod.txt # contextvars -importlib-metadata==4.0.1 +importlib-metadata==4.5.0 # via # -r requirements/prod.txt # cumulusci # flake8 # keyring + # markdown + # mkdocs # pep517 # pluggy # pre-commit @@ -151,10 +158,10 @@ jinja2==2.11.3 # via # -r requirements/prod.txt # cumulusci - # myst-parser + # mkdocs # snowfakery # sphinx -jwcrypto==0.8 +jwcrypto==0.9 # via # -r requirements/prod.txt # cumulusci @@ -167,10 +174,8 @@ lxml==4.6.3 # via # -r requirements/prod.txt # cumulusci -markdown-it-py==1.1.0 - # via - # mdit-py-plugins - # myst-parser +markdown==3.3.4 + # via mkdocs markupsafe==1.1.1 # via # -r requirements/prod.txt @@ -178,18 +183,19 @@ markupsafe==1.1.1 # jinja2 mccabe==0.6.1 # via flake8 -mdit-py-plugins==0.2.8 - # via myst-parser +mergedeep==1.3.4 + # via mkdocs +mkdocs==1.2.1 + # via -r requirements/dev.in multidict==5.1.0 # via yarl mypy-extensions==0.4.3 # via black -myst-parser==0.14.0 - # via -r requirements/dev.in nodeenv==1.6.0 # via pre-commit packaging==20.9 # via + # mkdocs # pytest # sphinx # tox @@ -245,6 +251,7 @@ python-dateutil==2.8.1 # -r requirements/prod.txt # cumulusci # faker + # ghp-import # github3.py # snowfakery pytz==2021.1 @@ -253,12 +260,15 @@ pytz==2021.1 # babel # cumulusci # fs +pyyaml-env-tag==0.1 + # via mkdocs pyyaml==5.4.1 # via # -r requirements/prod.txt # cumulusci - # myst-parser + # mkdocs # pre-commit + # pyyaml-env-tag # snowfakery # vcrpy regex==2021.4.4 @@ -285,7 +295,7 @@ robotframework-lint==1.1 # via # -r requirements/prod.txt # cumulusci -robotframework-pabot==1.13 +robotframework-pabot==2.0.0 # via # -r requirements/prod.txt # cumulusci @@ -298,10 +308,15 @@ robotframework-requests==0.9.1 # via # -r requirements/prod.txt # cumulusci -robotframework-seleniumlibrary==4.5.0 +robotframework-seleniumlibrary==5.1.3 # via # -r requirements/prod.txt # cumulusci +robotframework-stacktrace==0.4.0 + # via + # -r requirements/prod.txt + # cumulusci + # robotframework-pabot robotframework==4.0.3 # via # -r requirements/prod.txt @@ -310,6 +325,7 @@ robotframework==4.0.3 # robotframework-pabot # robotframework-requests # robotframework-seleniumlibrary + # robotframework-stacktrace rst2ansi==0.1.5 # via # -r requirements/prod.txt @@ -337,6 +353,7 @@ six==1.16.0 # -r requirements/prod.txt # cumulusci # fs + # jwcrypto # python-dateutil # responses # salesforce-bulk @@ -350,9 +367,7 @@ snowfakery==1.12 # -r requirements/prod.txt # cumulusci sphinx==3.5.4 - # via - # -r requirements/dev.in - # myst-parser + # via -r requirements/dev.in sphinxcontrib-applehelp==1.0.2 # via sphinx sphinxcontrib-devhelp==1.0.2 @@ -365,7 +380,7 @@ sphinxcontrib-qthelp==1.0.3 # via sphinx sphinxcontrib-serializinghtml==1.1.5 # via sphinx -sqlalchemy==1.4.15 +sqlalchemy==1.4.17 # via # -r requirements/prod.txt # cumulusci @@ -403,7 +418,6 @@ typing-extensions==3.10.0.0 # black # cumulusci # importlib-metadata - # markdown-it-py # pydantic # snowfakery # yarl @@ -417,7 +431,7 @@ uritemplate==3.0.1 # -r requirements/prod.txt # cumulusci # github3.py -urllib3==1.26.4 +urllib3==1.26.5 # via # -r requirements/prod.txt # cumulusci @@ -432,8 +446,14 @@ virtualenv==20.4.7 # via # pre-commit # tox +watchdog==2.1.2 + # via mkdocs wrapt==1.12.1 - # via vcrpy + # via + # -r requirements/prod.txt + # cumulusci + # deprecated + # vcrpy xmltodict==0.12.0 # via # -r requirements/prod.txt diff --git a/requirements/prod.txt b/requirements/prod.txt index cce4cb48..03ef1ea1 100644 --- a/requirements/prod.txt +++ b/requirements/prod.txt @@ -8,11 +8,11 @@ appdirs==1.4.4 # via # cumulusci # fs -authlib==0.15.3 +authlib==0.15.4 # via # cumulusci # simple-salesforce -certifi==2020.12.5 +certifi==2021.5.30 # via # cumulusci # requests @@ -38,11 +38,15 @@ cryptography==3.4.7 # authlib # cumulusci # jwcrypto -cumulusci==3.36.0 +cumulusci==3.37.0 # via -r requirements/prod.in +deprecated==1.2.12 + # via + # cumulusci + # jwcrypto docutils==0.16 # via cumulusci -faker==8.2.1 +faker==8.6.0 # via # -r requirements/prod.in # cumulusci @@ -70,7 +74,7 @@ idna==2.10 # requests immutables==0.15 # via contextvars -importlib-metadata==4.0.1 +importlib-metadata==4.5.0 # via # cumulusci # keyring @@ -80,7 +84,7 @@ jinja2==2.11.3 # -r requirements/prod.in # cumulusci # snowfakery -jwcrypto==0.8 +jwcrypto==0.9 # via # cumulusci # github3.py @@ -131,7 +135,7 @@ requests==2.25.1 # simple-salesforce robotframework-lint==1.1 # via cumulusci -robotframework-pabot==1.13 +robotframework-pabot==2.0.0 # via cumulusci robotframework-pythonlibcore==2.2.1 # via @@ -139,8 +143,12 @@ robotframework-pythonlibcore==2.2.1 # robotframework-seleniumlibrary robotframework-requests==0.9.1 # via cumulusci -robotframework-seleniumlibrary==4.5.0 +robotframework-seleniumlibrary==5.1.3 # via cumulusci +robotframework-stacktrace==0.4.0 + # via + # cumulusci + # robotframework-pabot robotframework==4.0.3 # via # cumulusci @@ -148,6 +156,7 @@ robotframework==4.0.3 # robotframework-pabot # robotframework-requests # robotframework-seleniumlibrary + # robotframework-stacktrace rst2ansi==0.1.5 # via cumulusci salesforce-bulk==2.2.0 @@ -166,11 +175,12 @@ six==1.16.0 # via # cumulusci # fs + # jwcrypto # python-dateutil # salesforce-bulk snowfakery==1.12 # via cumulusci -sqlalchemy==1.4.15 +sqlalchemy==1.4.17 # via # -r requirements/prod.in # cumulusci @@ -196,11 +206,15 @@ uritemplate==3.0.1 # via # cumulusci # github3.py -urllib3==1.26.4 +urllib3==1.26.5 # via # cumulusci # requests # selenium +wrapt==1.12.1 + # via + # cumulusci + # deprecated xmltodict==0.12.0 # via cumulusci zipp==3.4.1 diff --git a/setup.py b/setup.py index d90dfa51..7d8e34d6 100644 --- a/setup.py +++ b/setup.py @@ -49,7 +49,8 @@ def parse_requirements_file(requirements_file) -> List[str]: "console_scripts": [ "snowfakery=snowfakery.cli:main", "snowbench=snowfakery.tools.snowbench:main", - ] + ], + "mkdocs.plugins": ["snowfakery_fakes=snowfakery.tools.mkdocs:Plugin"], }, long_description=long_description, long_description_content_type="text/markdown", diff --git a/snowfakery/docs/examples/secret_life_of_pets.yml b/snowfakery/docs/examples/secret_life_of_pets.yml index 9cb6b17f..ec5e9e82 100644 --- a/snowfakery/docs/examples/secret_life_of_pets.yml +++ b/snowfakery/docs/examples/secret_life_of_pets.yml @@ -7,6 +7,6 @@ - object: Animal fields: name: - fake: first_name + fake: FirstName owner: reference: Person diff --git a/snowfakery/fakedata/fake_data_generator.py b/snowfakery/fakedata/fake_data_generator.py index 41802566..30a7184c 100644 --- a/snowfakery/fakedata/fake_data_generator.py +++ b/snowfakery/fakedata/fake_data_generator.py @@ -1,33 +1,35 @@ from difflib import get_close_matches -from faker import Faker import typing as T +from faker import Faker, Generator + class FakeNames(T.NamedTuple): f: Faker - def Username(self): + def user_name(self): + "Salesforce-style username in the form of an email address" return f"{self.f.first_name()}_{self.f.last_name()}_{self.f.uuid4()}@{self.f.hostname()}" - def Alias(self): + def alias(self): + "Salesforce-style 8-character alias" return self.f.first_name()[0:8] - def FirstName(self): - return self.f.first_name() - - def LastName(self): - return self.f.last_name() - - def Email(self): + def email(self): + """Email address using one of the "example" domains""" return self.f.ascii_safe_email() - def RealisticMaybeRealEmail(self): + def realistic_maybe_real_email(self): + """Like fake: email except that the email domain may be real and therefore + the email address itself may be real. Use with caution, you might + accidentally email strangers!!! + """ return self.f.email() # we will use this to exclude Faker's internal book-keeping methods # from our faker interface -faker_class_attrs = set(dir(Faker)) +faker_class_attrs = set(dir(Faker)).union((dir(Generator))) class FakeData: @@ -35,6 +37,10 @@ class FakeData: def __init__(self, faker: Faker): fake_names = FakeNames(faker) + self.faker = faker + + def no_underscore_name(name): + return name.lower().replace("_", "") def obj_to_func_list(obj: object, canonicalizer: T.Callable, ignore_list: set): return { @@ -49,11 +55,10 @@ def obj_to_func_list(obj: object, canonicalizer: T.Callable, ignore_list: set): # include snowfakery names defined above self.fake_names = { **obj_to_func_list(faker, str.lower, faker_class_attrs), - **obj_to_func_list( - faker, lambda x: x.lower().replace("_", ""), faker_class_attrs - ), + **obj_to_func_list(faker, no_underscore_name, faker_class_attrs), # in case of conflict, snowfakery names "win" over Faker names **obj_to_func_list(fake_names, str.lower, set()), + **obj_to_func_list(fake_names, no_underscore_name, set()), } def _get_fake_data(self, origname, *args, **kwargs): diff --git a/snowfakery/tools/mkdocs.py b/snowfakery/tools/mkdocs.py new file mode 100644 index 00000000..2bd058c2 --- /dev/null +++ b/snowfakery/tools/mkdocs.py @@ -0,0 +1,24 @@ +import sys +from pathlib import Path +from importlib import import_module +from unittest.mock import patch + +from mkdocs.plugins import BasePlugin + + +class Plugin(BasePlugin): + def on_config(self, config): + """Look for and load main_mkdocs_plugin in tools/faker_docs_utils/mkdocs_plugins.py + This bootstrap plugin is needed because that other one is never "installed" + It is just present in the repo. So it can't have an official entry point + in setup.py. + """ + print(config) + docs_dir = config["docs_dir"] + plugins_dir = Path(docs_dir).parent / "tools/faker_docs_utils/mkdocs_plugins" + new_sys_path = [*sys.path, str(plugins_dir)] + with patch.object(sys, "path", new_sys_path): + module = import_module("main_mkdocs_plugin") + main_plugin = module.Plugin() + config["plugins"]["main_mkdocs_plugin"] = main_plugin + main_plugin.on_config(config) diff --git a/tools/faker_docs.py b/tools/faker_docs.py new file mode 100644 index 00000000..0e63067e --- /dev/null +++ b/tools/faker_docs.py @@ -0,0 +1,12 @@ +from tools.faker_docs_utils.faker_markdown import generate_markdown_for_fakers + + +outfile = "docs/fakedata/en_US.md" +with open(outfile, "w") as o: + generate_markdown_for_fakers(o, "en_US") + +outfile = "docs/fakedata/fr_FR.md" +with open(outfile, "w") as o: + generate_markdown_for_fakers(o, "fr_FR") + +print("DONE", outfile) diff --git a/tools/faker_docs_utils/docs_config.yml b/tools/faker_docs_utils/docs_config.yml new file mode 100644 index 00000000..9d37c936 --- /dev/null +++ b/tools/faker_docs_utils/docs_config.yml @@ -0,0 +1,29 @@ +common_fakes: + - company + - name + - name_female + - name_male + - last_name + - first_name + - first_name_female + - first_name_male + - first_name_nonbinary + - catch_phrase + - year + - email + - phone_number + - building_number + - city + - state + - postalcode + - administrative_unit + - street_address + - country + - country_code + - current_country + - current_country_code + - time + - paragraph + - word + - sentence + - text diff --git a/tools/faker_docs_utils/docstring.py b/tools/faker_docs_utils/docstring.py new file mode 100644 index 00000000..304352c4 --- /dev/null +++ b/tools/faker_docs_utils/docstring.py @@ -0,0 +1,246 @@ +# Based on https://github.com/joke2k/faker/blob/2dac486e6d3b5f018feb524f6fa19917ec10299e/faker/sphinx/docstring.py +# Copied under the provisions of the MIT License + +# coding=utf-8 +import inspect +import logging +import re + +from collections import namedtuple + +from faker import Faker +from faker.config import AVAILABLE_LOCALES, DEFAULT_LOCALE +from .validator import SampleCodeValidator + +logger = logging.getLogger(__name__) +_fake = Faker(AVAILABLE_LOCALES) +_base_provider_method_pattern = re.compile( + r"^faker\.providers\.BaseProvider\.(?P\w+)$" +) +_standard_provider_method_pattern = re.compile( + r"^faker\.providers\.\w+\.Provider\.(?P\w+)$" +) +_locale_provider_method_pattern = re.compile( + r"^faker\.providers\.\w+" + r"\.(?P[a-z]{2,3}_[A-Z]{2})" + r"\.Provider" + r"\.(?P\w+)$", +) +_sample_line_pattern = re.compile( + r"^:sample" + r"(?: size=(?P[1-9][0-9]*))?" + r"(?: seed=(?P[0-9]+))?" + r":" + r"(?: ?(?P.*))?$", +) +_command_template = "generator.{method}({kwargs})" +_sample_output_template = ( + ">>> Faker.seed({seed})\n" + ">>> for _ in range({size}):\n" + "... fake.{method}({kwargs})\n" + "...\n" + "{results}\n\n" +) + +DEFAULT_SAMPLE_SIZE = 5 +DEFAULT_SEED = 0 +Sample = namedtuple("Sample", ["size", "seed", "kwargs"]) + + +class ProviderMethodDocstring: + """ + Class that preprocesses provider method docstrings to generate sample usage and output + + Notes on how samples are generated: + - If the docstring belongs to a standard provider method, sample usage and output will be + generated using a `Faker` object in the `DEFAULT_LOCALE`. + - If the docstring belongs to a localized provider method, the correct locale will be used. + - If the docstring does not belong to any provider method, docstring preprocessing will be skipped. + - Docstring lines will be parsed for potential sample sections, and the generation details of each + sample section will internally be represented as a ``Sample`` namedtuple. + - Each ``Sample`` will have info on the keyword arguments to pass to the provider method, how many + times the provider method will be called, and the initial seed value to ``Faker.seed()``. + """ + + def __init__(self, app, what, name, obj, options, lines): + self._line_iter = iter(lines) + self._parsed_lines = [] + self._samples = [] + self._skipped = True + self._log_prefix = f"{inspect.getfile(obj)}:docstring of {name}: WARNING:" + + if what != "method": + return + + base_provider_method_match = _base_provider_method_pattern.match(name) + locale_provider_method_match = _locale_provider_method_pattern.match(name) + standard_provider_method_match = _standard_provider_method_pattern.match(name) + if base_provider_method_match: + groupdict = base_provider_method_match.groupdict() + self._method = groupdict["method"] + self._locale = DEFAULT_LOCALE + elif standard_provider_method_match: + groupdict = standard_provider_method_match.groupdict() + self._method = groupdict["method"] + self._locale = DEFAULT_LOCALE + elif locale_provider_method_match: + groupdict = locale_provider_method_match.groupdict() + self._method = groupdict["method"] + self._locale = groupdict["locale"] + else: + return + + self._skipped = False + self._parse() + self._generate_samples() + + def _log_warning(self, warning): + logger.warning(f"{self._log_prefix} {warning}") + + def _parse(self): + while True: + try: + line = next(self._line_iter) + except StopIteration: + break + else: + self._parse_section(line) + + def _parse_section(self, section): + # No-op if section does not look like the start of a sample section + if not section.startswith(":sample"): + self._parsed_lines.append(section) + return + + try: + next_line = next(self._line_iter) + except StopIteration: + # No more lines left to consume, so save current sample section + self._process_sample_section(section) + return + + # Next line is the start of a new sample section, so process + # current sample section, and start parsing the new section + if next_line.startswith(":sample"): + self._process_sample_section(section) + self._parse_section(next_line) + + # Next line is an empty line indicating the end of + # current sample section, so process current section + elif next_line == "": + self._process_sample_section(section) + + # Section is assumed to be multiline, so continue + # adding lines to current sample section + else: + section = section + next_line + self._parse_section(section) + + def _process_sample_section(self, section): + match = _sample_line_pattern.match(section) + + # Discard sample section if malformed + if not match: + msg = f"The section `{section}` is malformed and will be discarded." + self._log_warning(msg) + return + + # Set sample generation defaults and do some beautification if necessary + groupdict = match.groupdict() + size = groupdict.get("size") + seed = groupdict.get("seed") + kwargs = groupdict.get("kwargs") + size = max(int(size), DEFAULT_SAMPLE_SIZE) if size else DEFAULT_SAMPLE_SIZE + seed = int(seed) if seed else DEFAULT_SEED + kwargs = self._beautify_kwargs(kwargs) if kwargs else "" + + # Store sample generation details + sample = Sample(size, seed, kwargs) + self._samples.append(sample) + + def _beautify_kwargs(self, kwargs): + def _repl_whitespace(match): + quoted = match.group(1) or match.group(2) + return quoted if quoted else "" + + def _repl_comma(match): + quoted = match.group(1) or match.group(2) + return quoted if quoted else ", " + + # First, remove all whitespaces and tabs not within quotes + result = re.sub(r'("[^"]*")|(\'[^\']*\')|[ \t]+', _repl_whitespace, kwargs) + + # Next, insert a whitespace after each comma not within quotes + result = re.sub(r'("[^"]*")|(\'[^\']*\')|,', _repl_comma, result) + + # Then return the result with all leading and trailing whitespaces stripped + return result.strip() + + def _stringify_result(self, value): + return repr(value) + + def _generate_eval_scope(self): + from collections import ( + OrderedDict, + ) # noqa: F401 Do not remove! The eval command needs this reference. + + return { + "generator": _fake[self._locale], + "OrderedDict": OrderedDict, + } + + def _inject_default_sample_section(self): + default_sample = Sample(DEFAULT_SAMPLE_SIZE, DEFAULT_SEED, "") + self._samples.append(default_sample) + + def _generate_samples(self): + if not self._samples: + self._inject_default_sample_section() + + output = "" + eval_scope = self._generate_eval_scope() + for sample in self._samples: + command = _command_template.format( + method=self._method, kwargs=sample.kwargs + ) + validator = SampleCodeValidator(command) + if validator.errors: + msg = ( + f"Invalid code elements detected. Sample generation will be " + f"skipped for method `{self._method}` with arguments `{sample.kwargs}`." + ) + self._log_warning(msg) + continue + + try: + Faker.seed(sample.seed) + results = "\n".join( + [ + self._stringify_result(eval(command, eval_scope)) + for _ in range(sample.size) + ] + ) + except Exception as e: + msg = f"Sample generation failed for method `{self._method}` with arguments `{sample.kwargs}`: {e}." + self._log_warning(msg) + continue + else: + output += _sample_output_template.format( + seed=sample.seed, + method=self._method, + kwargs=sample.kwargs, + size=sample.size, + results=results, + ) + + if output: + output = ":examples:\n\n" + output + self._parsed_lines.extend(output.split("\n")) + + @property + def skipped(self): + return self._skipped + + @property + def lines(self): + return self._parsed_lines diff --git a/tools/faker_docs_utils/faker_markdown.py b/tools/faker_docs_utils/faker_markdown.py new file mode 100644 index 00000000..1c061590 --- /dev/null +++ b/tools/faker_docs_utils/faker_markdown.py @@ -0,0 +1,134 @@ +import re +from functools import lru_cache +from pathlib import Path + +from faker import Faker +from faker.config import AVAILABLE_LOCALES +from tools.faker_docs_utils.format_samples import yaml_samples_for_docstring +from tools.faker_docs_utils.summarize_fakers import get_all_fakers + +from snowfakery.fakedata.fake_data_generator import FakeData + +_RE_COMBINE_WHITESPACE = re.compile(r"(?<=^) +", re.MULTILINE) +_RE_STRIP_SAMPLES = re.compile(r"^\s*:sample:.*$", re.MULTILINE) +_COMMENT_LINES_THAT_LOOK_LIKE_TITLES = re.compile(r"^#", re.MULTILINE) + +non_countries = ("fr_QC", "ar_AA") +AVAILABLE_LOCALES = [ + locale + for locale in AVAILABLE_LOCALES + if locale not in non_countries and "_" in locale +] + + +def strip(my_str): + my_str = _RE_COMBINE_WHITESPACE.sub("", my_str) + my_str = _RE_STRIP_SAMPLES.sub("", my_str).strip() + my_str = _COMMENT_LINES_THAT_LOOK_LIKE_TITLES.sub(" #", my_str) + my_str = my_str.replace(":example", "Example:") + return my_str + + +@lru_cache(maxsize=1000) +def country_for_locale(locale: str): + f = Faker(locale) + return f.current_country() + + +def other_locales(current_locale: str): + def format_link(locale: str): + try: + country_name = country_for_locale(locale) + except (ValueError, AttributeError): + return None + link_text = f"{locale} : {country_name}" + return f" - [{link_text}]({locale}.md)\n" + + other_locales = [locale for locale in AVAILABLE_LOCALES if locale != current_locale] + links = [format_link(locale) for locale in other_locales] + return " ".join(link for link in links if link) + + +def generate_markdown_for_fakers(outfile, locale): + faker = Faker(locale) + fd = FakeData(faker) + + all_fakers = get_all_fakers(fd) + + def output(*args, **kwargs): + print(*args, **kwargs, file=outfile) + + output(f"# Fake Data: {locale}\n") + output( + f"Current Locale: {locale} ({faker.current_country()}) [[Other Locales](#other-locales)]" + ) + output() + output("[TOC]\n") + + output("## Commonly Used\n") + summarize_categories(output, [f for f in all_fakers if f.common], "", locale) + output("## Rarely Used\n") + summarize_categories(output, [f for f in all_fakers if not f.common], "", locale) + locales = other_locales(locale) + if locales: + output("## Other Locales\n") + output(locales) + + +def summarize_categories(output, fakers, common: str, locale): + categorized = categorize(fakers) + for category_name, fakers in categorized.items(): + output(f"### {category_name.title()} Fakers\n") + for faker in fakers: + output_faker(faker.name, faker, output, locale) + + +def categorize(fakers): + categories = {} + for fakerdata in fakers: + category = fakerdata.category + categories.setdefault(category, []) + categories[category].append(fakerdata) + return {name: value for name, value in sorted(categories.items())} + + +def output_faker(name, data, output, locale): + output(f"#### fake: {name}\n") + if strip(data.doc): + output(strip(data.doc)) + output() + + output("Aliases: ", ", ".join(data.aliases)) + output() + link = f"[{data.source}]({data.url})" + output("Source:", link) + samples = yaml_samples_for_docstring(name, data.fullname, data.doc, locale) + samples = list(filter(None, samples)) + if samples: + output() + output("##### Samples") + output() + for sample in samples: + yaml, out = sample + output("Recipe:\n") + output(indent(yaml)) + output("Outputs:\n") + output(indent(out)) + else: + output() + + +def indent(yaml): + lines = yaml.split("\n") + + def prefix(line): + return " " if line.strip() else "" + + lines = [prefix(line) + line for line in lines] + return "\n".join(lines) + + +def generate_markdown_for_all_locales(path: Path, locales=AVAILABLE_LOCALES): + for locale in locales: + with Path(path, f"{locale}.md").open("w") as f: + generate_markdown_for_fakers(f, locale) diff --git a/tools/faker_docs_utils/format_samples.py b/tools/faker_docs_utils/format_samples.py new file mode 100644 index 00000000..1efd1947 --- /dev/null +++ b/tools/faker_docs_utils/format_samples.py @@ -0,0 +1,152 @@ +import ast +import yaml + +from io import StringIO +from collections import OrderedDict +from unittest.mock import MagicMock + +from snowfakery import generate_data + +from . import docstring + + +def samples_from_docstring(fullname, docstring_data): + lines = docstring_data.split("\n") + lines = [line.strip() for line in lines] + docstrings = docstring.ProviderMethodDocstring( + app=MagicMock(), + what="method", + name=fullname, + obj=MagicMock, + options=MagicMock(), + lines=lines, + ) + return docstrings._samples + + +def simplify(arg): + fieldname = arg._fields[0] + out = getattr(arg, fieldname) + if isinstance(out, (str, int, float, bool)): + return out + if isinstance(out, (list, tuple)): + args = [simplify(a) for a in out] + return type(out)(args) + if isinstance(out, (OrderedDict, dict)): + return {name: simplify(value) for name, value in dict(out).items()} + raise TypeError(type(out), out) + + +def extract_keywords(kwargstr): + fake_python = f"Func({kwargstr})" + tree = ast.parse(fake_python, mode="eval") + kwds = {arg.arg: simplify(arg.value) for arg in tree.body.keywords} + return kwds + + +def reformat_yaml(yaml_data): + data = yaml.safe_load(yaml_data) + return yaml.dump(data, sort_keys=False) + + +def yaml_samples_for_docstring_sample(name, sample, locale): + try: + return yaml_samples_for_docstring_sample_inner(name, sample, locale) + except Exception as e: + print("Cannot generate sample for", sample, str(e)[0:100]) + raise e + + +def yaml_samples_for_docstring_sample_inner(name, sample, locale): + try: + kwds = extract_keywords(sample.kwargs) + except Exception as e: + print("Cannot extract keywords", sample, str(e)[0:100]) + return None + + name = name.split(".")[-1] + return yaml_sample(name, kwds, sample.kwargs, locale) + + +def yaml_sample(name, kwds, kw_example, locale): + if kwds: + inline_example = f"fake.{name}({kw_example})" + block_example = {f"fake.{name}": kwds} + else: + inline_example = f"fake.{name}" + block_example = {"fake": name} + + inline_example = "${{" + inline_example + "}}" + + if ":" in inline_example: + inline_example = f'"{inline_example}"' + + yaml_data = f""" + - object: Example + fields: + inline_example: {inline_example} + block_example: {block_example}""" + + if locale: + locale_decl = f""" + - var: snowfakery_locale + value: {locale} + """ + yaml_data = locale_decl + yaml_data + try: + yaml_data = reformat_yaml(yaml_data) + except Exception as e: + print("CANNOT PARSE") + print(yaml_data) + print(str(e)[0:100]) + raise + + with StringIO() as s: + try: + generate_data(StringIO(yaml_data), output_file=s, output_format="txt") + except Exception as e: + print("Cannot generate") + print(yaml_data) + print(str(e)[0:100]) + output = s.getvalue() + if output: + return yaml_data, output + + +def default_yaml_sample(name, locale): + return yaml_sample(name, None, None, locale) + + +def yaml_samples_for_docstring(name, fullname, docstring_data, locale=None): + sample_objs = samples_from_docstring(fullname, docstring_data) + + output = [ + yaml_samples_for_docstring_sample(name, sample, locale) + for sample in sample_objs + ] + if not output: + output = [default_yaml_sample(name, locale)] + return output + + +if __name__ == "__main__": + + out = samples_from_docstring( + "faker.providers.BaseProvider.upc_e", + """ together to produce the UPC-E barcode, and attempting to convert the + barcode to UPC-A and back again to UPC-E will exhibit the behavior + described above. + + :sample: + :sample: base='123456' + :sample: base='123456', number_system_digit=0 + :sample: base='123456', number_system_digit=1 + :sample: base='120000', number_system_digit=0 + :sample: base='120003', number_system_digit=0 + :sample: base='120004', number_system_digit=0 + :sample: base='120000', number_system_digit=0, safe_mode=False + :sample: base='120003', number_system_digit=0, safe_mode=False + :sample: base='120004', number_system_digit=0, safe_mode=False""", + ) + + print(out) diff --git a/tools/faker_docs_utils/mkdocs_plugins/main_mkdocs_plugin.py b/tools/faker_docs_utils/mkdocs_plugins/main_mkdocs_plugin.py new file mode 100644 index 00000000..cc383f1d --- /dev/null +++ b/tools/faker_docs_utils/mkdocs_plugins/main_mkdocs_plugin.py @@ -0,0 +1,38 @@ +from pathlib import Path +import sys +import os +from unittest.mock import patch +from functools import lru_cache + +from mkdocs.plugins import BasePlugin +from faker.factory import Factory + + +class Plugin(BasePlugin): + def on_config(self, config): + pass + + def on_pre_build(self, config): + root_dir = Path(__file__).parent.parent.parent.parent + faker_docs_dir = root_dir / "docs/fakedata" + faker_docs_dir.mkdir(exist_ok=True) + new_sys_path = [*sys.path, str(root_dir)] + print("Note: Hiding warnings during build", __file__) + + # make modules available + sys_path_patch = patch.object(sys, "path", new_sys_path) + + # speed up a critical function + lru_patch = patch( + "faker.factory.Factory._get_provider_class", + lru_cache(maxsize=10_000)(Factory._get_provider_class), + ) + + with sys_path_patch, lru_patch, open(os.devnull, "w") as devnull, patch.object( + sys, "stdout", devnull + ): + from tools.faker_docs_utils.faker_markdown import ( + generate_markdown_for_all_locales, + ) + + generate_markdown_for_all_locales(faker_docs_dir) diff --git a/tools/faker_docs_utils/summarize_fakers.py b/tools/faker_docs_utils/summarize_fakers.py new file mode 100644 index 00000000..2292040e --- /dev/null +++ b/tools/faker_docs_utils/summarize_fakers.py @@ -0,0 +1,65 @@ +from pathlib import Path +import types +import typing as T + +import yaml + + +def get_all_fakers(faker): + from snowfakery.utils.collections import CaseInsensitiveDict + + with (Path(__file__).parent / "docs_config.yml").open() as f: + common_fakes = yaml.safe_load(f)["common_fakes"] + + faker_infos = CaseInsensitiveDict() + for name, meth in faker.fake_names.items(): + if not isinstance(meth, types.MethodType): + continue + friendly = _to_camel_case(name) + func = meth.__func__ + doc = func.__doc__ + filename = func.__code__.co_filename + cls = meth.__self__.__class__ + fullname = cls.__module__ + "." + cls.__name__ + "." + meth.__name__ + is_common = meth.__name__ in common_fakes + if "/faker/" in filename: + source = "faker" + idx = filename.find("/faker/") + url = "https://github.com/joke2k/faker/tree/master" + filename[idx:] + parts = filename.split("/") + while parts[-1] in ("__init__.py", "en_US"): + del parts[-1] + category = parts[-1] + else: + source = "snowfakery" + idx = filename.find("/snowfakery/") + url = ( + "https://github.com/SFDO-Tooling/Snowfakery/tree/main" + filename[idx:] + ) + category = "Salesforce" + + faker_info = faker_infos.setdefault( + friendly, + FakerInfo( + friendly, fullname, [], url, source, category, doc or "", is_common + ), + ) + faker_info.aliases.append(name) + + return faker_infos.values() + + +class FakerInfo(T.NamedTuple): + name: str + fullname: str + aliases: T.List[str] + url: str + source: str + category: str + doc: str + common: bool + + +def _to_camel_case(snake_str): + components = snake_str.split("_") + return "".join(x.title() for x in components) diff --git a/tools/faker_docs_utils/validator.py b/tools/faker_docs_utils/validator.py new file mode 100644 index 00000000..7cd87bb0 --- /dev/null +++ b/tools/faker_docs_utils/validator.py @@ -0,0 +1,154 @@ +# Based on https://github.com/joke2k/faker/blob/2dac486e6d3b5f018feb524f6fa19917ec10299e/faker/sphinx/validator.py +# Copied under the provisions of the MIT License + +# coding=utf-8 +import ast +import traceback + +from collections import OrderedDict + + +class SampleCodeValidator(ast.NodeVisitor): + """ + Class that checks if a string is a valid and "safe" Python expression + + What is considered "safe" for this class is limited to the context of generating + provider method sample code and output for documentation purposes. The end goal + is to pass a command string to `eval()` should the string pass the validation + performed by this class. + + The main assumption this class will make is that the command string passed during + class instantiation will always be in the form "{generator}.{method}({arguments})". + In said form, {generator} is a `Generator` object variable that already exists + within the scope where `eval()` will be called, {method} will be the provider + method name which is also available within the `eval()` scope, and {arguments} + will be sample arguments parsed from docstrings. This means that {arguments} can + potentially be used as a vector for code injection. + + In order to neuter the impact of code injection, the following validation steps + will be applied: + + - The command string is parsed using 'eval' mode, meaning expressions only. + - The command string can only have whitelisted code elements. See `_whitelisted_nodes`. + - The command string can only have one instance of variable access. + - The command string can only have one instance of attribute access. + - The command string can only have one instance of a function/method call. + - The argument values in the command string can only be literals. + - The only literals allowed are numbers (integers, floats, or complex numbers), + strings (but not f-strings), bytes, lists, tuples, sets, dictionaries, True, + False, and None. + + There is, however, an exception. In order to accommodate sample code with custom + probability distribution, variable access to `OrderedDict` will not count against + the maximum limit of variable access, and invoking `OrderedDict` constructor calls + will not count against the maximum limit of function/method calls. In order to + neuter the impact of code injection, please ensure that `OrderedDict` refers to + the standard library's `collections.OrderedDict` within the `eval()` scope before + passing the command string to `eval()` for execution. This can be done in code review. + """ + + _whitelisted_nodes = ( + # Code elements related to function calls and variable and attribute access + ast.Expression, + ast.Call, + ast.Attribute, + ast.Name, + ast.Load, + ast.keyword, + # Code elements representing whitelisted literals + ast.Num, + ast.Str, + ast.Bytes, + ast.List, + ast.Tuple, + ast.Set, + ast.Dict, + ast.NameConstant, + ) + + _max_function_call_count = 1 + _max_attribute_access_count = 1 + _max_variable_access_count = 1 + + def __init__(self, command): + self._errors = set() + self._function_call_count = 0 + self._attribute_access_count = 0 + self._variable_access_count = 0 + self._command = command + + try: + self._tree = ast.parse(command, mode="eval") + except (SyntaxError, ValueError): + self._log_error(traceback.format_exc()) + else: + self._validate() + + @property + def errors(self): + return self._errors + + def _is_whitelisted(self, node): + return isinstance(node, self._whitelisted_nodes) + + def _log_error(self, msg): + self._errors.add(msg) + + def _validate(self): + self.visit(self._tree) + + def _is_node_using_ordereddict(self, node): + is_valid = False + + # If instance of function call, check if it is a call to the OrderedDict constructor + if isinstance(node, ast.Call): + is_valid = self._is_node_using_ordereddict(node.func) + + # If instance of variable access, check if it is + elif isinstance(node, ast.Name) and node.id == OrderedDict.__name__: + is_valid = True + + return is_valid + + def visit(self, node): + # Check if code element type is allowed + if not self._is_whitelisted(node): + msg = "Code element `%s` is not allowed." % node.__class__.__name__ + self._log_error(msg) + + return super().visit(node) + + def visit_Call(self, node): + if not self._is_node_using_ordereddict(node): + # There can only be one instance of a function call + if self._function_call_count < self._max_function_call_count: + self._function_call_count += 1 + else: + msg = "There can only be one instance of a function/method call." + self._log_error(msg) + + # Proceed to child nodes + self.generic_visit(node) + + def visit_Attribute(self, node): + # There can only be one instance of attribute access + if self._attribute_access_count < self._max_attribute_access_count: + self._attribute_access_count += 1 + else: + msg = "There can only be one instance of attribute access." + self._log_error(msg) + + # Proceed to child nodes + self.generic_visit(node) + + def visit_Name(self, node): + if not self._is_node_using_ordereddict(node): + # There can only be one instance of variable access + if self._variable_access_count < self._max_variable_access_count: + self._variable_access_count += 1 + else: + msg = "There can only be one instance of variable access." + self._log_error(msg) + + # Proceed to child nodes + self.generic_visit(node) From 0e54aab97b6438abd02830b9456bee07c235c912 Mon Sep 17 00:00:00 2001 From: Paul Prescod Date: Sun, 13 Jun 2021 14:07:36 -0700 Subject: [PATCH 05/53] Conditional locale building --- Makefile | 4 +- docs/fakedata.md | 7483 +++++++++++++++++ mkdocs.yml | 4 +- snowfakery/tools/mkdocs.py | 7 +- tools/faker_docs_utils/faker_markdown.py | 31 +- .../mkdocs_plugins/main_mkdocs_plugin.py | 10 +- 6 files changed, 7528 insertions(+), 11 deletions(-) create mode 100644 docs/fakedata.md diff --git a/Makefile b/Makefile index b5e5b282..c9867a59 100644 --- a/Makefile +++ b/Makefile @@ -5,5 +5,7 @@ update-deps: dev-install: pip-sync requirements/*.txt -doc: +docs: .FORCE python -m mkdocs build --clean --site-dir build/html --config-file mkdocs.yml + +.FORCE: \ No newline at end of file diff --git a/docs/fakedata.md b/docs/fakedata.md new file mode 100644 index 00000000..40ec6865 --- /dev/null +++ b/docs/fakedata.md @@ -0,0 +1,7483 @@ +# Fake Data: en_US + +The basic concepts of fake data are described in +the [main docs](index.md#fake-data). + +Current Locale: en_US (United States) + + +Our fake data can be localized to many languages. We have +[detailed docs](https://snowfakery.readthedocs.io/en/feature-fake-data-docs/locales.html) +about the other languages. + +[TOC] + +## Commonly Used + +### Salesforce Fakers + +#### fake: Email + +Email address using one of the "example" domains + +Aliases: email + +Source: [snowfakery](https://github.com/SFDO-Tooling/Snowfakery/tree/main/snowfakery/fakedata/fake_data_generator.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.Email}} + block_example: + fake: Email + +Outputs: + + Example(id=1, inline_example=dakotagaines@example.org, block_example=thurst@example.net) + +### Address Fakers + +#### fake: AdministrativeUnit + +Aliases: administrative_unit, administrativeunit + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/address/en_US/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.AdministrativeUnit}} + block_example: + fake: AdministrativeUnit + +Outputs: + + Example(id=1, inline_example=North Carolina, block_example=New York) + +#### fake: BuildingNumber + +Example: '791' + +Aliases: building_number, buildingnumber + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/address/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.BuildingNumber}} + block_example: + fake: BuildingNumber + +Outputs: + + Example(id=1, inline_example=15781, block_example=6593) + +#### fake: City + +Example: 'Sashabury' + +Aliases: city + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/address/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.City}} + block_example: + fake: City + +Outputs: + + Example(id=1, inline_example=New Raymondside, block_example=West Edgar) + +#### fake: Country + +Aliases: country + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/address/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.Country}} + block_example: + fake: Country + +Outputs: + + Example(id=1, inline_example=Armenia, block_example=Eritrea) + +#### fake: CountryCode + +Aliases: country_code, countrycode + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/address/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.CountryCode}} + block_example: + fake: CountryCode + +Outputs: + + Example(id=1, inline_example=SE, block_example=RU) + +#### fake: CurrentCountry + +Aliases: current_country, currentcountry + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/address/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.CurrentCountry}} + block_example: + fake: CurrentCountry + +Outputs: + + Example(id=1, inline_example=United States, block_example=United States) + +#### fake: CurrentCountryCode + +Aliases: current_country_code, currentcountrycode + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/address/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.CurrentCountryCode}} + block_example: + fake: CurrentCountryCode + +Outputs: + + Example(id=1, inline_example=US, block_example=US) + +#### fake: Postalcode + +Aliases: postalcode + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/address/en_US/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.Postalcode}} + block_example: + fake: Postalcode + +Outputs: + + Example(id=1, inline_example=67514, block_example=64192) + +#### fake: State + +Aliases: state + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/address/en_US/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.State}} + block_example: + fake: State + +Outputs: + + Example(id=1, inline_example=North Carolina, block_example=New York) + +#### fake: StreetAddress + +Example: '791 Crist Parks' + +Aliases: street_address, streetaddress + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/address/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.StreetAddress}} + block_example: + fake: StreetAddress + +Outputs: + + Example(id=1, inline_example=93328 Ortiz Common, block_example=714 Knox Crossing Suite 839) + +### Company Fakers + +#### fake: CatchPhrase + +Example: 'Robust full-range hub' + +Aliases: catch_phrase, catchphrase + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/company/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.CatchPhrase}} + block_example: + fake: CatchPhrase + +Outputs: + + Example(id=1, inline_example=Devolved executive challenge, block_example=Versatile bandwidth-monitored process improvement) + +#### fake: Company + +Example: 'Acme Ltd' + +Aliases: company + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/company/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.Company}} + block_example: + fake: Company + +Outputs: + + Example(id=1, inline_example=Krause-Wilcox, block_example=Bautista, Callahan and Davila) + +### Date_Time Fakers + +#### fake: Time + +Get a time string (24h format by default) +:param pattern format +Example: '15:02:34' + +Aliases: time + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/date_time/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.Time}} + block_example: + fake: Time + +Outputs: + + Example(id=1, inline_example=19:09:38, block_example=16:37:16) + +#### fake: Year + +Aliases: year + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/date_time/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.Year}} + block_example: + fake: Year + +Outputs: + + Example(id=1, inline_example=2003, block_example=1997) + +### Lorem Fakers + +#### fake: Paragraph + +Generate a paragraph. + +The ``nb_sentences`` argument controls how many sentences the paragraph +will contain, and setting ``variable_nb_sentences`` to ``False`` will +generate the exact amount, while setting it to ``True`` (default) will +generate a random amount (+/-40%, minimum of 1) using +|randomize_nb_elements|. + +Under the hood, |sentences| is used to generate the sentences, so the +argument ``ext_word_list`` works in the same way here as it would in +that method. + + + + +ext_word_list=['abc', 'def', 'ghi', 'jkl'] + +Aliases: paragraph + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/lorem/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.Paragraph(nb_sentences=5)}} + block_example: + fake.Paragraph: + nb_sentences: 5 + +Outputs: + + Example(id=1, inline_example=Others kind company likely. Tonight themselves true power home price. Night actually score from. Name care several., block_example=Particular pull opportunity throughout take car. Hold increase practice ability court. Civil development large report purpose themselves. I reduce industry. Close ask reduce. Month maintain no sense this manager fine.) + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.Paragraph(nb_sentences=5, variable_nb_sentences=False)}} + block_example: + fake.Paragraph: + nb_sentences: 5 + variable_nb_sentences: false + +Outputs: + + Example(id=1, inline_example=Anyone state wind indeed nature white without. Would I question first. Add senior woman put partner. Budget power them evidence without. Little type physical against., block_example=Son break either president stage population boy. Everything affect American race. Fire happen nothing support suffer which parent. Republican total policy head Mrs debate onto. Catch even front.) + +#### fake: Sentence + +Generate a sentence. + +The ``nb_words`` argument controls how many words the sentence will +contain, and setting ``variable_nb_words`` to ``False`` will generate +the exact amount, while setting it to ``True`` (default) will generate +a random amount (+/-40%, minimum of 1) using |randomize_nb_elements|. + +Under the hood, |words| is used to generate the words, so the argument +``ext_word_list`` works in the same way here as it would in that method. + + + + +ext_word_list=['abc', 'def', 'ghi', 'jkl'] + +Aliases: sentence + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/lorem/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.Sentence(nb_words=10)}} + block_example: + fake.Sentence: + nb_words: 10 + +Outputs: + + Example(id=1, inline_example=Feeling fact by four two data son., block_example=Onto knowledge other his offer face country cost party prevent live bed serious.) + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.Sentence(nb_words=10, variable_nb_words=False)}} + block_example: + fake.Sentence: + nb_words: 10 + variable_nb_words: false + +Outputs: + + Example(id=1, inline_example=Theory type successful together type music hospital relate every speech., block_example=Support time operation wear often late produce you true soldier.) + +#### fake: Text + +Generate a text string. + +The ``max_nb_chars`` argument controls the approximate number of +characters the text string will have, and depending on its value, this +method may use either |words|, |sentences|, or |paragraphs| for text +generation. The ``ext_word_list`` argument works in exactly the same way +it would in any of those methods. + +Aliases: text + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/lorem/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.Text(max_nb_chars=20)}} + block_example: + fake.Text: + max_nb_chars: 20 + +Outputs: + + Example(id=1, inline_example=Book pick method., block_example=Organization into.) + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.Text(max_nb_chars=80)}} + block_example: + fake.Text: + max_nb_chars: 80 + +Outputs: + + Example(id=1, inline_example=There many true follow marriage material. Myself use act relationship section., block_example=Family relationship like son might trip at candidate.) + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.Text(max_nb_chars=160)}} + block_example: + fake.Text: + max_nb_chars: 160 + +Outputs: + + Example(id=1, inline_example=Measure too maybe off question source. Wrong section town deal movement out stay lot. Parent do ten after those scientist., block_example=Individual man tell response purpose character would. + Partner hit another. Sing after our car food record power. Himself simply make thing particular.) + +#### fake: Word + +Generate a word. + +This method uses |words| under the hood with the ``nb`` argument set to +``1`` to generate the result. + +Aliases: word + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/lorem/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.Word}} + block_example: + fake: Word + +Outputs: + + Example(id=1, inline_example=interview, block_example=why) + +### Person Fakers + +#### fake: FirstName + +Aliases: first_name, firstname + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/person/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.FirstName}} + block_example: + fake: FirstName + +Outputs: + + Example(id=1, inline_example=Danielle, block_example=Vernon) + +#### fake: FirstNameFemale + +Aliases: first_name_female, firstnamefemale + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/person/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.FirstNameFemale}} + block_example: + fake: FirstNameFemale + +Outputs: + + Example(id=1, inline_example=Krista, block_example=Jasmine) + +#### fake: FirstNameMale + +Aliases: first_name_male, firstnamemale + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/person/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.FirstNameMale}} + block_example: + fake: FirstNameMale + +Outputs: + + Example(id=1, inline_example=Logan, block_example=Jared) + +#### fake: FirstNameNonbinary + +Aliases: first_name_nonbinary, firstnamenonbinary + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/person/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.FirstNameNonbinary}} + block_example: + fake: FirstNameNonbinary + +Outputs: + + Example(id=1, inline_example=Danielle, block_example=Vernon) + +#### fake: LastName + +Aliases: last_name, lastname + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/person/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.LastName}} + block_example: + fake: LastName + +Outputs: + + Example(id=1, inline_example=Goodwin, block_example=Hendrix) + +#### fake: Name + +Example: 'John Doe' + +Aliases: name + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/person/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.Name}} + block_example: + fake: Name + +Outputs: + + Example(id=1, inline_example=Morgan Escobar, block_example=Jay Coleman II) + +#### fake: NameFemale + +Aliases: name_female, namefemale + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/person/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.NameFemale}} + block_example: + fake: NameFemale + +Outputs: + + Example(id=1, inline_example=Morgan Escobar DDS, block_example=Briana Moon MD) + +#### fake: NameMale + +Aliases: name_male, namemale + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/person/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.NameMale}} + block_example: + fake: NameMale + +Outputs: + + Example(id=1, inline_example=Ruben Escobar III, block_example=Chris Moon II) + +### Phone_Number Fakers + +#### fake: PhoneNumber + +Aliases: phone_number, phonenumber + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/phone_number/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.PhoneNumber}} + block_example: + fake: PhoneNumber + +Outputs: + + Example(id=1, inline_example=484-185-8398, block_example=001-471-965-9342) + +## Rarely Used + +### Salesforce Fakers + +#### fake: UserName + +Salesforce-style username in the form of an email address + +Aliases: user_name, username + +Source: [snowfakery](https://github.com/SFDO-Tooling/Snowfakery/tree/main/snowfakery/fakedata/fake_data_generator.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.UserName}} + block_example: + fake: UserName + +Outputs: + + Example(id=1, inline_example=Kevin_Dodson_fb3675b8-9cde-43e6-8870-e15c2fcd81b5@email-47.sullivan.com, block_example=James_Terrell_e5eeac76-148b-4758-97ab-792809e469e6@email-86.morrow.com) + +#### fake: Alias + +Salesforce-style 8-character alias + +Aliases: alias + +Source: [snowfakery](https://github.com/SFDO-Tooling/Snowfakery/tree/main/snowfakery/fakedata/fake_data_generator.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.Alias}} + block_example: + fake: Alias + +Outputs: + + Example(id=1, inline_example=Martin, block_example=Priscill) + +#### fake: RealisticMaybeRealEmail + +Like fake: email except that the email domain may be real and therefore +the email address itself may be real. Use with caution, you might +accidentally email strangers!!! + +Aliases: realistic_maybe_real_email, realisticmayberealemail + +Source: [snowfakery](https://github.com/SFDO-Tooling/Snowfakery/tree/main/snowfakery/fakedata/fake_data_generator.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.RealisticMaybeRealEmail}} + block_example: + fake: RealisticMaybeRealEmail + +Outputs: + + Example(id=1, inline_example=holly75@gmail.com, block_example=langpenny@hotmail.com) + +### Address Fakers + +#### fake: Address + +Example: '791 Crist Parks, Sashabury, IL 86039-9874' + +Aliases: address + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/address/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.Address}} + block_example: + fake: Address + +Outputs: + + Example(id=1, inline_example=848 Martin Springs Suite 947 + Claystad, MD 80819, block_example=533 Sean Crescent Apt. 525 + Gouldton, WY 19684) + +#### fake: CityPrefix + +Aliases: city_prefix, cityprefix + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/address/en_US/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.CityPrefix}} + block_example: + fake: CityPrefix + +Outputs: + + Example(id=1, inline_example=West, block_example=New) + +#### fake: CitySuffix + +Example: 'town' + +Aliases: city_suffix, citysuffix + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/address/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.CitySuffix}} + block_example: + fake: CitySuffix + +Outputs: + + Example(id=1, inline_example=fort, block_example=furt) + +#### fake: MilitaryApo + +Example: 'PSC 5394 Box 3492 + +Aliases: military_apo, militaryapo + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/address/en_US/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.MilitaryApo}} + block_example: + fake: MilitaryApo + +Outputs: + + Example(id=1, inline_example=PSC 8016, Box 0975, block_example=PSC 3513, Box 9332) + +#### fake: MilitaryDpo + +Example: 'Unit 3333 Box 9342' + +Aliases: military_dpo, militarydpo + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/address/en_US/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.MilitaryDpo}} + block_example: + fake: MilitaryDpo + +Outputs: + + Example(id=1, inline_example=Unit 8016 Box 0975, block_example=Unit 3513 Box 9332) + +#### fake: MilitaryShip + +Example: 'USS' + +Aliases: military_ship, militaryship + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/address/en_US/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.MilitaryShip}} + block_example: + fake: MilitaryShip + +Outputs: + + Example(id=1, inline_example=USCGC, block_example=USNV) + +#### fake: MilitaryState + +Example: 'APO' + +Aliases: military_state, militarystate + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/address/en_US/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.MilitaryState}} + block_example: + fake: MilitaryState + +Outputs: + + Example(id=1, inline_example=AA, block_example=AA) + +#### fake: PostalcodeInState + +Aliases: postalcode_in_state, postalcodeinstate + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/address/en_US/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.PostalcodeInState}} + block_example: + fake: PostalcodeInState + +Outputs: + + Example(id=1, inline_example=97914, block_example=62068) + +#### fake: PostalcodePlus4 + +Aliases: postalcode_plus4, postalcodeplus4 + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/address/en_US/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.PostalcodePlus4}} + block_example: + fake: PostalcodePlus4 + +Outputs: + + Example(id=1, inline_example=76966-3579, block_example=66651-2282) + +#### fake: Postcode + +Aliases: postcode + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/address/en_US/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.Postcode}} + block_example: + fake: Postcode + +Outputs: + + Example(id=1, inline_example=67514, block_example=64192) + +#### fake: PostcodeInState + +:returns: A random postcode within the provided state abbreviation + +:param state_abbr: A state abbreviation + +Aliases: postcode_in_state, postcodeinstate + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/address/en_US/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.PostcodeInState}} + block_example: + fake: PostcodeInState + +Outputs: + + Example(id=1, inline_example=97914, block_example=62068) + +#### fake: SecondaryAddress + +Aliases: secondary_address, secondaryaddress + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/address/en_US/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.SecondaryAddress}} + block_example: + fake: SecondaryAddress + +Outputs: + + Example(id=1, inline_example=Suite 115, block_example=Suite 815) + +#### fake: StateAbbr + +:returns: A random state or territory abbreviation. + +:param include_territories: If True, territories will be included. +If False, only states will be returned. + +Aliases: state_abbr, stateabbr + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/address/en_US/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.StateAbbr}} + block_example: + fake: StateAbbr + +Outputs: + + Example(id=1, inline_example=ME, block_example=MI) + +#### fake: StreetName + +Example: 'Crist Parks' + +Aliases: street_name, streetname + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/address/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.StreetName}} + block_example: + fake: StreetName + +Outputs: + + Example(id=1, inline_example=Dwayne River, block_example=Krause Place) + +#### fake: StreetSuffix + +Example: 'Avenue' + +Aliases: street_suffix, streetsuffix + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/address/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.StreetSuffix}} + block_example: + fake: StreetSuffix + +Outputs: + + Example(id=1, inline_example=Green, block_example=Pass) + +#### fake: Zipcode + +Aliases: zipcode + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/address/en_US/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.Zipcode}} + block_example: + fake: Zipcode + +Outputs: + + Example(id=1, inline_example=67514, block_example=64192) + +#### fake: ZipcodeInState + +Aliases: zipcode_in_state, zipcodeinstate + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/address/en_US/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.ZipcodeInState}} + block_example: + fake: ZipcodeInState + +Outputs: + + Example(id=1, inline_example=97914, block_example=62068) + +#### fake: ZipcodePlus4 + +Aliases: zipcode_plus4, zipcodeplus4 + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/address/en_US/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.ZipcodePlus4}} + block_example: + fake: ZipcodePlus4 + +Outputs: + + Example(id=1, inline_example=76966-3579, block_example=66651-2282) + +### Automotive Fakers + +#### fake: LicensePlate + +Generate a license plate. + +Aliases: license_plate, licenseplate + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/automotive/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.LicensePlate}} + block_example: + fake: LicensePlate + +Outputs: + + Example(id=1, inline_example=938 NK7, block_example=40-Q801) + +### Bank Fakers + +#### fake: BankCountry + +Generate the bank provider's ISO 3166-1 alpha-2 country code. + +Aliases: bank_country, bankcountry + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/bank/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.BankCountry}} + block_example: + fake: BankCountry + +Outputs: + + Example(id=1, inline_example=GB, block_example=GB) + +#### fake: Bban + +Generate a Basic Bank Account Number (BBAN). + +Aliases: bban + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/bank/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.Bban}} + block_example: + fake: Bban + +Outputs: + + Example(id=1, inline_example=FBTV47112201868483, block_example=GVSN94775159179533) + +#### fake: Iban + +Generate an International Bank Account Number (IBAN). + +Aliases: iban + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/bank/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.Iban}} + block_example: + fake: Iban + +Outputs: + + Example(id=1, inline_example=GB68FBTV47112201868483, block_example=GB71GVSN94775159179533) + +#### fake: Swift + +Generate a SWIFT code. + +SWIFT codes, reading from left to right, are composed of a 4 alphabet +character bank code, a 2 alphabet character country code, a 2 +alphanumeric location code, and an optional 3 alphanumeric branch code. +This means SWIFT codes can only have 8 or 11 characters, so the value of +``length`` can only be ``None`` or the integers ``8`` or ``11``. If the +value is ``None``, then a value of ``8`` or ``11`` will randomly be +assigned. + +Because all 8-digit SWIFT codes already refer to the primary branch or +office, the ``primary`` argument only has an effect if the value of +``length`` is ``11``. If ``primary`` is ``True`` and ``length`` is +``11``, the 11-digit SWIFT codes generated will always end in ``'XXX'`` +to denote that they belong to primary branches/offices. + +For extra authenticity, localized providers may opt to include SWIFT +bank codes, location codes, and branch codes used in their respective +locales. If ``use_dataset`` is ``True``, this method will generate SWIFT +codes based on those locale-specific codes if included. If those codes +were not included, then it will behave as if ``use_dataset`` were +``False``, and in that mode, all those codes will just be randomly +generated as per the specification. + +Aliases: swift + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/bank/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.Swift}} + block_example: + fake: Swift + +Outputs: + + Example(id=1, inline_example=VKPRGBGW, block_example=KTUGGB9427Q) + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.Swift(length=8)}} + block_example: + fake.Swift: + length: 8 + +Outputs: + + Example(id=1, inline_example=BZRAGBFZ, block_example=WZVUGBA5) + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.Swift(length=8, use_dataset=True)}} + block_example: + fake.Swift: + length: 8 + use_dataset: true + +Outputs: + + Example(id=1, inline_example=KHXKGBEM, block_example=SHHZGBJ8) + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.Swift(length=11)}} + block_example: + fake.Swift: + length: 11 + +Outputs: + + Example(id=1, inline_example=OCCKGB65GT9, block_example=JWDRGBV8N9S) + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.Swift(length=11, primary=True)}} + block_example: + fake.Swift: + length: 11 + primary: true + +Outputs: + + Example(id=1, inline_example=OCTZGBYUXXX, block_example=SHJFGBMLXXX) + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.Swift(length=11, use_dataset=True)}} + block_example: + fake.Swift: + length: 11 + use_dataset: true + +Outputs: + + Example(id=1, inline_example=BTVIGB4EFIJ, block_example=BCWRGBZ7R7P) + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.Swift(length=11, primary=True, use_dataset=True)}} + block_example: + fake.Swift: + length: 11 + primary: true + use_dataset: true + +Outputs: + + Example(id=1, inline_example=GVSNGBR2XXX, block_example=PVUWGBWFXXX) + +#### fake: Swift11 + +Generate an 11-digit SWIFT code. + +This method uses |swift| under the hood with the ``length`` argument set +to ``11``. If ``primary`` is set to ``True``, the SWIFT code will always +end with ``'XXX'``. All 11-digit SWIFT codes use this convention to +refer to the primary branch/office. + +Aliases: swift11 + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/bank/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.Swift11}} + block_example: + fake: Swift11 + +Outputs: + + Example(id=1, inline_example=TPKHGBUEMOP, block_example=ZEZRGB2FFU6) + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.Swift11(use_dataset=True)}} + block_example: + fake.Swift11: + use_dataset: true + +Outputs: + + Example(id=1, inline_example=PDJRGBSH9V8, block_example=GZTRGBS2FYU) + +#### fake: Swift8 + +Generate an 8-digit SWIFT code. + +This method uses |swift| under the hood with the ``length`` argument set +to ``8`` and with the ``primary`` argument omitted. All 8-digit SWIFT +codes already refer to the primary branch/office. + +Aliases: swift8 + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/bank/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.Swift8}} + block_example: + fake: Swift8 + +Outputs: + + Example(id=1, inline_example=XCVKGB49, block_example=DLNKGBN9) + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.Swift8(use_dataset=True)}} + block_example: + fake.Swift8: + use_dataset: true + +Outputs: + + Example(id=1, inline_example=POQIGBD9, block_example=ACXMGBA5) + +### Barcode Fakers + +#### fake: Ean + +Generate an EAN barcode of the specified ``length``. + +The value of ``length`` can only be ``8`` or ``13`` (default) which will +create an EAN-8 or an EAN-13 barcode respectively. + +If a value for ``prefixes`` is specified, the result will begin with one +of the sequences in ``prefixes``. + +Aliases: ean + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/barcode/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.Ean(length=13)}} + block_example: + fake.Ean: + length: 13 + +Outputs: + + Example(id=1, inline_example=1858398947198, block_example=6593423209470) + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.Ean(length=8)}} + block_example: + fake.Ean: + length: 8 + +Outputs: + + Example(id=1, inline_example=11220183, block_example=68483395) + +#### fake: Ean13 + +Generate an EAN-13 barcode. + +If ``leading_zero`` is ``True``, the leftmost digit of the barcode will +be set to ``0``. If ``False``, the leftmost digit cannot be ``0``. If +``None`` (default), the leftmost digit can be any digit. + +If a value for ``prefixes`` is specified, the result will begin with one +of the sequences in ``prefixes`` and will ignore ``leading_zero``. + +This method uses the standard barcode provider's |ean13| under the +hood with the ``prefixes`` argument set to the correct value to attain +the behavior described above. + +.. note:: +EAN-13 barcode that starts with a zero can be converted to UPC-A +by dropping the leading zero. This may cause problems with readers +that treat all of these code as UPC-A codes and drop the first digit +when reading it. + +You can set the argument ``prefixes`` ( or ``leading_zero`` for +convenience) explicitly to avoid or to force the generated barcode to +start with a zero. You can also generate actual UPC-A barcode with +|EnUsBarcodeProvider.upc_a|. + +Aliases: ean13 + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/barcode/en_US/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.Ean13}} + block_example: + fake: Ean13 + +Outputs: + + Example(id=1, inline_example=1858398947198, block_example=6593423209470) + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.Ean13(leading_zero=False)}} + block_example: + fake.Ean13: + leading_zero: false + +Outputs: + + Example(id=1, inline_example=2220186848335, block_example=5751591795336) + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.Ean13(leading_zero=True)}} + block_example: + fake.Ean13: + leading_zero: true + +Outputs: + + Example(id=1, inline_example=135256012306, block_example=0139916151091) + +#### fake: Ean8 + +Generate an EAN-8 barcode. + +This method uses |ean| under the hood with the ``length`` argument +explicitly set to ``8``. + +If a value for ``prefixes`` is specified, the result will begin with one +of the sequences in ``prefixes``. + +Aliases: ean8 + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/barcode/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.Ean8}} + block_example: + fake: Ean8 + +Outputs: + + Example(id=1, inline_example=80160977, block_example=53513939) + +#### fake: LocalizedEan + +Generate a localized EAN barcode of the specified ``length``. + +The value of ``length`` can only be ``8`` or ``13`` (default) which will +create an EAN-8 or an EAN-13 barcode respectively. + +This method uses the standard barcode provider's |ean| under the hood +with the ``prefixes`` argument explicitly set to ``local_prefixes`` of +a localized barcode provider implementation. + +Aliases: localized_ean, localizedean + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/barcode/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.LocalizedEan}} + block_example: + fake: LocalizedEan + +Outputs: + + Example(id=1, inline_example=301609753510, block_example=0432871158717) + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.LocalizedEan(length=13)}} + block_example: + fake.LocalizedEan: + length: 13 + +Outputs: + + Example(id=1, inline_example=118583989473, block_example=0759342320948) + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.LocalizedEan(length=8)}} + block_example: + fake.LocalizedEan: + length: 8 + +Outputs: + + Example(id=1, inline_example=10220184, block_example=13483395) + +#### fake: LocalizedEan13 + +Generate a localized EAN-13 barcode. + +This method uses |localized_ean| under the hood with the ``length`` +argument explicitly set to ``13``. + +Aliases: localized_ean13, localizedean13 + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/barcode/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.LocalizedEan13}} + block_example: + fake: LocalizedEan13 + +Outputs: + + Example(id=1, inline_example=948418583985, block_example=0019659342324) + +#### fake: LocalizedEan8 + +Generate a localized EAN-8 barcode. + +This method uses |localized_ean| under the hood with the ``length`` +argument explicitly set to ``8``. + +Aliases: localized_ean8, localizedean8 + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/barcode/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.LocalizedEan8}} + block_example: + fake: LocalizedEan8 + +Outputs: + + Example(id=1, inline_example=7016097, block_example=03513934) + +#### fake: UpcA + +Generate a 12-digit UPC-A barcode. + +The value of ``upc_ae_mode`` controls how barcodes will be generated. If +``False`` (default), barcodes are not guaranteed to have a UPC-E +equivalent. In this mode, the method uses |EnUsBarcodeProvider.ean13| +under the hood, and the values of ``base`` and ``number_system_digit`` +will be ignored. + +If ``upc_ae_mode`` is ``True``, the resulting barcodes are guaranteed to +have a UPC-E equivalent, and the values of ``base`` and +``number_system_digit`` will be used to control what is generated. + +Under this mode, ``base`` is expected to have a 6-digit string value. If +any other value is supplied, a random 6-digit string will be used +instead. As for ``number_system_digit``, the expected value is a ``0`` +or a ``1``. If any other value is provided, this method will randomly +choose from the two. + +.. important:: +When ``upc_ae_mode`` is enabled, you might encounter instances where +different values of ``base`` (e.g. ``'120003'`` and ``'120004'``) +produce the same UPC-A barcode. This is normal, and the reason lies +within the whole conversion process. To learn more about this and +what ``base`` and ``number_system_digit`` actually represent, please +refer to |EnUsBarcodeProvider.upc_e|. + +Aliases: upc_a, upca + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/barcode/en_US/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.UpcA}} + block_example: + fake: UpcA + +Outputs: + + Example(id=1, inline_example=604876475933, block_example=219489241150) + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.UpcA(upc_ae_mode=True, number_system_digit=0)}} + block_example: + fake.UpcA: + upc_ae_mode: true + number_system_digit: 0 + +Outputs: + + Example(id=1, inline_example=81565000094, block_example=038770000081) + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.UpcA(upc_ae_mode=True, number_system_digit=1)}} + block_example: + fake.UpcA: + upc_ae_mode: true + number_system_digit: 1 + +Outputs: + + Example(id=1, inline_example=108000000164, block_example=197100005353) + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.UpcA(upc_ae_mode=True, base='123456', number_system_digit=0)}} + block_example: + fake.UpcA: + upc_ae_mode: true + base: '123456' + number_system_digit: 0 + +Outputs: + + Example(id=1, inline_example=12345000065, block_example=039332000082) + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.UpcA(upc_ae_mode=True, base='120003', number_system_digit=0)}} + block_example: + fake.UpcA: + upc_ae_mode: true + base: '120003' + number_system_digit: 0 + +Outputs: + + Example(id=1, inline_example=12000000003, block_example=071158000075) + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.UpcA(upc_ae_mode=True, base='120004', number_system_digit=0)}} + block_example: + fake.UpcA: + upc_ae_mode: true + base: '120004' + number_system_digit: 0 + +Outputs: + + Example(id=1, inline_example=12000000003, block_example=014841000082) + +#### fake: UpcE + +Generate an 8-digit UPC-E barcode. + +UPC-E barcodes can be expressed in 6, 7, or 8-digit formats, but this +method uses the 8 digit format, since it is trivial to convert to the +other two formats. The first digit (starting from the left) is +controlled by ``number_system_digit``, and it can only be a ``0`` or a +``1``. The last digit is the check digit that is inherited from the +UPC-E barcode's UPC-A equivalent. The middle six digits are collectively +referred to as the ``base`` (for a lack of a better term). + +On that note, this method uses ``base`` and ``number_system_digit`` to +first generate a UPC-A barcode for the check digit, and what happens +next depends on the value of ``safe_mode``. The argument ``safe_mode`` +exists, because there are some UPC-E values that share the same UPC-A +equivalent. For example, any UPC-E barcode of the form ``abc0000d``, +``abc0003d``, and ``abc0004d`` share the same UPC-A value +``abc00000000d``, but that UPC-A value will only convert to ``abc0000d`` +because of (a) how UPC-E is just a zero-suppressed version of UPC-A and +(b) the rules around the conversion. + +If ``safe_mode`` is ``True`` (default), this method performs another set +of conversions to guarantee that the UPC-E barcodes generated can be +converted to UPC-A, and that UPC-A barcode can be converted back to the +original UPC-E barcode. Using the example above, even if the bases +``120003`` or ``120004`` are used, the resulting UPC-E barcode will +always use the base ``120000``. + +If ``safe_mode`` is ``False``, then the ``number_system_digit``, +``base``, and the computed check digit will just be concatenated +together to produce the UPC-E barcode, and attempting to convert the +barcode to UPC-A and back again to UPC-E will exhibit the behavior +described above. + +Aliases: upc_e, upce + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/barcode/en_US/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.UpcE}} + block_example: + fake: UpcE + +Outputs: + + Example(id=1, inline_example=16604872, block_example=04759386) + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.UpcE(base='123456')}} + block_example: + fake.UpcE: + base: '123456' + +Outputs: + + Example(id=1, inline_example=11234562, block_example=02194899) + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.UpcE(base='123456', number_system_digit=0)}} + block_example: + fake.UpcE: + base: '123456' + number_system_digit: 0 + +Outputs: + + Example(id=1, inline_example=1234565, block_example=04115786) + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.UpcE(base='123456', number_system_digit=1)}} + block_example: + fake.UpcE: + base: '123456' + number_system_digit: 1 + +Outputs: + + Example(id=1, inline_example=11234562, block_example=11565933) + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.UpcE(base='120000', number_system_digit=0)}} + block_example: + fake.UpcE: + base: '120000' + number_system_digit: 0 + +Outputs: + + Example(id=1, inline_example=1200003, block_example=08778400) + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.UpcE(base='120003', number_system_digit=0)}} + block_example: + fake.UpcE: + base: '120003' + number_system_digit: 0 + +Outputs: + + Example(id=1, inline_example=1200003, block_example=08016946) + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.UpcE(base='120004', number_system_digit=0)}} + block_example: + fake.UpcE: + base: '120004' + number_system_digit: 0 + +Outputs: + + Example(id=1, inline_example=1200003, block_example=07535137) + +### Color Fakers + +#### fake: Color + +Generate a color in a human-friendly way. + +Under the hood, this method first creates a color represented in the HSV +color model and then converts it to the desired ``color_format``. The +argument ``hue`` controls the H value according to the following +rules: + +- If the value is a number from ``0`` to ``360``, it will serve as the H +value of the generated color. +- If the value is a tuple/list of 2 numbers from 0 to 360, the color's H +value will be randomly selected from that range. +- If the value is a valid string, the color's H value will be randomly +selected from the H range corresponding to the supplied string. Valid +values are ``'monochrome'``, ``'red'``, ``'orange'``, ``'yellow'``, +``'green'``, ``'blue'``, ``'purple'``, and ``'pink'``. + +The argument ``luminosity`` influences both S and V values and is +partially affected by ``hue`` as well. The finer details of this +relationship are somewhat involved, so please refer to the source code +instead if you wish to dig deeper. To keep the interface simple, this +argument either can be omitted or can accept the following string +values:``'bright'``, ``'dark'``, ``'light'``, or ``'random'``. + +The argument ``color_format`` controls in which color model the color is +represented. Valid values are ``'hsv'``, ``'hsl'``, ``'rgb'``, or +``'hex'`` (default). + +Aliases: color + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/color/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.Color(hue='red')}} + block_example: + fake.Color: + hue: red + +Outputs: + + Example(id=1, inline_example=#e5909b, block_example=#ff977a) + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.Color(luminosity='light')}} + block_example: + fake.Color: + luminosity: light + +Outputs: + + Example(id=1, inline_example=#f7afed, block_example=#f2de7d) + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.Color(hue='orange', luminosity='bright')}} + block_example: + fake.Color: + hue: orange + luminosity: bright + +Outputs: + + Example(id=1, inline_example=#cc9d04, block_example=#ba7112) + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.Color(hue=135, luminosity='dark', color_format='hsv')}} + block_example: + fake.Color: + hue: 135 + luminosity: dark + color_format: hsv + +Outputs: + + Example(id=1, inline_example=hsv(135, 96, 54), block_example=hsv(135, 98, 57)) + +#### fake: ColorName + +Generate a color name. + +Aliases: color_name, colorname + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/color/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.ColorName}} + block_example: + fake: ColorName + +Outputs: + + Example(id=1, inline_example=SlateBlue, block_example=PaleGreen) + +#### fake: HexColor + +Generate a color formatted as a hex triplet. + +Aliases: hex_color, hexcolor + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/color/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.HexColor}} + block_example: + fake: HexColor + +Outputs: + + Example(id=1, inline_example=#0a5d30, block_example=#42485f) + +#### fake: RgbColor + +Generate a color formatted as a comma-separated RGB value. + +Aliases: rgb_color, rgbcolor + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/color/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.RgbColor}} + block_example: + fake: RgbColor + +Outputs: + + Example(id=1, inline_example=75,158,50, block_example=37,169,241) + +#### fake: RgbCssColor + +Generate a color formatted as a CSS rgb() function. + +Aliases: rgb_css_color, rgbcsscolor + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/color/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.RgbCssColor}} + block_example: + fake: RgbCssColor + +Outputs: + + Example(id=1, inline_example=rgb(75,158,50), block_example=rgb(37,169,241)) + +#### fake: SafeColorName + +Generate a web-safe color name. + +Aliases: safe_color_name, safecolorname + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/color/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.SafeColorName}} + block_example: + fake: SafeColorName + +Outputs: + + Example(id=1, inline_example=black, block_example=olive) + +#### fake: SafeHexColor + +Generate a web-safe color formatted as a hex triplet. + +Aliases: safe_hex_color, safehexcolor + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/color/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.SafeHexColor}} + block_example: + fake: SafeHexColor + +Outputs: + + Example(id=1, inline_example=#449933, block_example=#22aaff) + +### Company Fakers + +#### fake: Bs + +Example: 'integrate extensible convergence' + +Aliases: bs + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/company/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.Bs}} + block_example: + fake: Bs + +Outputs: + + Example(id=1, inline_example=enable front-end channels, block_example=engineer mission-critical e-business) + +#### fake: CompanySuffix + +Example: 'Ltd' + +Aliases: company_suffix, companysuffix + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/company/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.CompanySuffix}} + block_example: + fake: CompanySuffix + +Outputs: + + Example(id=1, inline_example=Group, block_example=Group) + +### Credit_Card Fakers + +#### fake: CreditCardExpire + +Generate a credit card expiry date. + +This method uses |date_time_between| under the hood to generate the +expiry date, so the ``start`` and ``end`` arguments work in the same way +here as it would in that method. For the actual formatting of the expiry +date, |strftime| is used and ``date_format`` is simply passed +to that method. + +Aliases: credit_card_expire, creditcardexpire + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/credit_card/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.CreditCardExpire}} + block_example: + fake: CreditCardExpire + +Outputs: + + Example(id=1, inline_example=09/29, block_example=05/28) + +#### fake: CreditCardFull + +Generate a set of credit card details. + +Aliases: credit_card_full, creditcardfull + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/credit_card/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.CreditCardFull}} + block_example: + fake: CreditCardFull + +Outputs: + + Example(id=1, inline_example=Diners Club / Carte Blanche + Vanessa Koch + 30515917953300 01/26 + CVC: 135 + , block_example=VISA 16 digit + Ana Miranda + 4123098910139912 02/28 + CVC: 151 + ) + +#### fake: CreditCardNumber + +Generate a valid credit card number. + +Aliases: credit_card_number, creditcardnumber + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/credit_card/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.CreditCardNumber}} + block_example: + fake: CreditCardNumber + +Outputs: + + Example(id=1, inline_example=180071965934238, block_example=4947112201868487) + +#### fake: CreditCardProvider + +Generate a credit card provider name. + +Aliases: credit_card_provider, creditcardprovider + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/credit_card/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.CreditCardProvider}} + block_example: + fake: CreditCardProvider + +Outputs: + + Example(id=1, inline_example=Diners Club / Carte Blanche, block_example=Discover) + +#### fake: CreditCardSecurityCode + +Generate a credit card security code. + +Aliases: credit_card_security_code, creditcardsecuritycode + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/credit_card/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.CreditCardSecurityCode}} + block_example: + fake: CreditCardSecurityCode + +Outputs: + + Example(id=1, inline_example=924, block_example=157) + +### Currency Fakers + +#### fake: Cryptocurrency + +Aliases: cryptocurrency + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/currency/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.Cryptocurrency}} + block_example: + fake: Cryptocurrency + +Outputs: + + Example(id=1, inline_example=('USDT', 'Tether'), block_example=('ZEC', 'Zcash')) + +#### fake: CryptocurrencyCode + +Aliases: cryptocurrency_code, cryptocurrencycode + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/currency/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.CryptocurrencyCode}} + block_example: + fake: CryptocurrencyCode + +Outputs: + + Example(id=1, inline_example=USDT, block_example=ZEC) + +#### fake: CryptocurrencyName + +Aliases: cryptocurrency_name, cryptocurrencyname + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/currency/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.CryptocurrencyName}} + block_example: + fake: CryptocurrencyName + +Outputs: + + Example(id=1, inline_example=Tether, block_example=Zcash) + +#### fake: Currency + +Aliases: currency + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/currency/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.Currency}} + block_example: + fake: Currency + +Outputs: + + Example(id=1, inline_example=('SDG', 'Sudanese pound'), block_example=('NGN', 'Nigerian naira')) + +#### fake: CurrencyCode + +Aliases: currency_code, currencycode + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/currency/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.CurrencyCode}} + block_example: + fake: CurrencyCode + +Outputs: + + Example(id=1, inline_example=SDG, block_example=NGN) + +#### fake: CurrencyName + +Aliases: currency_name, currencyname + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/currency/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.CurrencyName}} + block_example: + fake: CurrencyName + +Outputs: + + Example(id=1, inline_example=Sudanese pound, block_example=Nigerian naira) + +#### fake: CurrencySymbol + +Example:: $ + +Aliases: currency_symbol, currencysymbol + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/currency/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.CurrencySymbol}} + block_example: + fake: CurrencySymbol + +Outputs: + + Example(id=1, inline_example=$, block_example=₦) + +#### fake: Pricetag + +Aliases: pricetag + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/currency/en_US/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.Pricetag}} + block_example: + fake: Pricetag + +Outputs: + + Example(id=1, inline_example=$1,784.08, block_example=$6.09) + +### Date_Time Fakers + +#### fake: AmPm + +Aliases: am_pm, ampm + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/date_time/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.AmPm}} + block_example: + fake: AmPm + +Outputs: + + Example(id=1, inline_example=PM, block_example=PM) + +#### fake: Century + +Example: 'XVII' + +Aliases: century + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/date_time/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.Century}} + block_example: + fake: Century + +Outputs: + + Example(id=1, inline_example=XVI, block_example=XIII) + +#### fake: Date + +Get a date string between January 1, 1970 and now +:param pattern format +Example: '2008-11-27' + +Aliases: date + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/date_time/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.Date}} + block_example: + fake: Date + +Outputs: + + Example(id=1, inline_example=2003-01-25, block_example=1997-07-22) + +#### fake: DateBetween + +Get a Date object based on a random date between two given dates. +Accepts date strings that can be recognized by strtotime(). + +:param start_date Defaults to 30 years ago +:param end_date Defaults to "today" +Example: Date('1999-02-02') +:return Date + +Aliases: date_between, datebetween + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/date_time/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.DateBetween}} + block_example: + fake: DateBetween + +Outputs: + + Example(id=1, inline_example=2000-04-03, block_example=2008-11-03) + +#### fake: DateBetweenDates + +Takes two Date objects and returns a random date between the two given dates. +Accepts Date or Datetime objects + +:param date_start: Date +:param date_end: Date +:return Date + +Aliases: date_between_dates, datebetweendates + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/date_time/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.DateBetweenDates}} + block_example: + fake: DateBetweenDates + +Outputs: + + Example(id=1, inline_example=2021-06-13, block_example=2021-06-13) + +#### fake: DateObject + +Get a date object between January 1, 1970 and now +Example: datetime.date(2016, 9, 20) + +Aliases: date_object, dateobject + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/date_time/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.DateObject}} + block_example: + fake: DateObject + +Outputs: + + Example(id=1, inline_example=2003-01-25, block_example=1997-07-22) + +#### fake: DateOfBirth + +Generate a random date of birth represented as a Date object, +constrained by optional miminimum_age and maximum_age +parameters. + +:param tzinfo Defaults to None. +:param minimum_age Defaults to 0. +:param maximum_age Defaults to 115. + +Example: Date('1979-02-02') +:return Date + +Aliases: date_of_birth, dateofbirth + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/date_time/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.DateOfBirth}} + block_example: + fake: DateOfBirth + +Outputs: + + Example(id=1, inline_example=1940-09-07, block_example=1975-01-12) + +#### fake: DateThisCentury + +Gets a Date object for the current century. + +:param before_today: include days in current century before today +:param after_today: include days in current century after today +Example: Date('2012-04-04') +:return Date + +Aliases: date_this_century, datethiscentury + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/date_time/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.DateThisCentury}} + block_example: + fake: DateThisCentury + +Outputs: + + Example(id=1, inline_example=2016-07-13, block_example=2013-10-11) + +#### fake: DateThisDecade + +Gets a Date object for the decade year. + +:param before_today: include days in current decade before today +:param after_today: include days in current decade after today +Example: Date('2012-04-04') +:return Date + +Aliases: date_this_decade, datethisdecade + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/date_time/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.DateThisDecade}} + block_example: + fake: DateThisDecade + +Outputs: + + Example(id=1, inline_example=2021-01-12, block_example=2020-11-10) + +#### fake: DateThisMonth + +Gets a Date object for the current month. + +:param before_today: include days in current month before today +:param after_today: include days in current month after today +:param tzinfo: timezone, instance of datetime.tzinfo subclass +Example: DateTime('2012-04-04 11:02:02') +:return DateTime + +Aliases: date_this_month, datethismonth + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/date_time/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.DateThisMonth}} + block_example: + fake: DateThisMonth + +Outputs: + + Example(id=1, inline_example=2021-06-01, block_example=2021-06-04) + +#### fake: DateThisYear + +Gets a Date object for the current year. + +:param before_today: include days in current year before today +:param after_today: include days in current year after today +Example: Date('2012-04-04') +:return Date + +Aliases: date_this_year, datethisyear + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/date_time/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.DateThisYear}} + block_example: + fake: DateThisYear + +Outputs: + + Example(id=1, inline_example=2021-04-10, block_example=2021-04-05) + +#### fake: DateTime + +Get a datetime object for a date between January 1, 1970 and now +:param tzinfo: timezone, instance of datetime.tzinfo subclass +Example: DateTime('2005-08-16 20:39:21') +:return datetime + +Aliases: date_time, datetime + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/date_time/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.DateTime}} + block_example: + fake: DateTime + +Outputs: + + Example(id=1, inline_example=2003-01-25 19:09:38, block_example=1997-07-22 16:37:16) + +#### fake: DateTimeAd + +Get a datetime object for a date between January 1, 001 and now +:param tzinfo: timezone, instance of datetime.tzinfo subclass +Example: DateTime('1265-03-22 21:15:52') +:return datetime + +Aliases: date_time_ad, datetimead + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/date_time/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.DateTimeAd}} + block_example: + fake: DateTimeAd + +Outputs: + + Example(id=1, inline_example=1877-01-02 08:15:53, block_example=0746-05-19 02:40:04) + +#### fake: DateTimeBetween + +Get a DateTime object based on a random date between two given dates. +Accepts date strings that can be recognized by strtotime(). + +:param start_date Defaults to 30 years ago +:param end_date Defaults to "now" +:param tzinfo: timezone, instance of datetime.tzinfo subclass +Example: DateTime('1999-02-02 11:42:52') +:return DateTime + +Aliases: date_time_between, datetimebetween + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/date_time/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.DateTimeBetween}} + block_example: + fake: DateTimeBetween + +Outputs: + + Example(id=1, inline_example=2000-04-05 02:13:35, block_example=2008-11-05 06:55:21) + +#### fake: DateTimeBetweenDates + +Takes two DateTime objects and returns a random datetime between the two +given datetimes. +Accepts DateTime objects. + +:param datetime_start: DateTime +:param datetime_end: DateTime +:param tzinfo: timezone, instance of datetime.tzinfo subclass +Example: DateTime('1999-02-02 11:42:52') +:return DateTime + +Aliases: date_time_between_dates, datetimebetweendates + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/date_time/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.DateTimeBetweenDates}} + block_example: + fake: DateTimeBetweenDates + +Outputs: + + Example(id=1, inline_example=2021-06-13 14:05:53, block_example=2021-06-13 14:05:53) + +#### fake: DateTimeThisCentury + +Gets a DateTime object for the current century. + +:param before_now: include days in current century before today +:param after_now: include days in current century after today +:param tzinfo: timezone, instance of datetime.tzinfo subclass +Example: DateTime('2012-04-04 11:02:02') +:return DateTime + +Aliases: date_time_this_century, datetimethiscentury + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/date_time/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.DateTimeThisCentury}} + block_example: + fake: DateTimeThisCentury + +Outputs: + + Example(id=1, inline_example=2016-07-13 21:34:49, block_example=2013-10-11 08:18:38) + +#### fake: DateTimeThisDecade + +Gets a DateTime object for the decade year. + +:param before_now: include days in current decade before today +:param after_now: include days in current decade after today +:param tzinfo: timezone, instance of datetime.tzinfo subclass +Example: DateTime('2012-04-04 11:02:02') +:return DateTime + +Aliases: date_time_this_decade, datetimethisdecade + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/date_time/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.DateTimeThisDecade}} + block_example: + fake: DateTimeThisDecade + +Outputs: + + Example(id=1, inline_example=2021-01-12 10:20:55, block_example=2020-11-10 12:31:09) + +#### fake: DateTimeThisMonth + +Gets a DateTime object for the current month. + +:param before_now: include days in current month before today +:param after_now: include days in current month after today +:param tzinfo: timezone, instance of datetime.tzinfo subclass +Example: DateTime('2012-04-04 11:02:02') +:return DateTime + +Aliases: date_time_this_month, datetimethismonth + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/date_time/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.DateTimeThisMonth}} + block_example: + fake: DateTimeThisMonth + +Outputs: + + Example(id=1, inline_example=2021-06-12 19:04:24, block_example=2021-06-10 19:53:28) + +#### fake: DateTimeThisYear + +Gets a DateTime object for the current year. + +:param before_now: include days in current year before today +:param after_now: include days in current year after today +:param tzinfo: timezone, instance of datetime.tzinfo subclass +Example: DateTime('2012-04-04 11:02:02') +:return DateTime + +Aliases: date_time_this_year, datetimethisyear + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/date_time/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.DateTimeThisYear}} + block_example: + fake: DateTimeThisYear + +Outputs: + + Example(id=1, inline_example=2021-04-10 06:42:46, block_example=2021-04-05 08:35:13) + +#### fake: DayOfMonth + +Aliases: day_of_month, dayofmonth + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/date_time/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.DayOfMonth}} + block_example: + fake: DayOfMonth + +Outputs: + + Example(id=1, inline_example=25, block_example=22) + +#### fake: DayOfWeek + +Aliases: day_of_week, dayofweek + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/date_time/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.DayOfWeek}} + block_example: + fake: DayOfWeek + +Outputs: + + Example(id=1, inline_example=Saturday, block_example=Tuesday) + +#### fake: FutureDate + +Get a Date object based on a random date between 1 day from now and a +given date. +Accepts date strings that can be recognized by strtotime(). + +:param end_date Defaults to "+30d" +:param tzinfo: timezone, instance of datetime.tzinfo subclass +Example: DateTime('1999-02-02 11:42:52') +:return DateTime + +Aliases: future_date, futuredate + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/date_time/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.FutureDate}} + block_example: + fake: FutureDate + +Outputs: + + Example(id=1, inline_example=2021-07-07, block_example=2021-07-03) + +#### fake: FutureDatetime + +Get a DateTime object based on a random date between 1 second form now +and a given date. +Accepts date strings that can be recognized by strtotime(). + +:param end_date Defaults to "+30d" +:param tzinfo: timezone, instance of datetime.tzinfo subclass +Example: DateTime('1999-02-02 11:42:52') +:return DateTime + +Aliases: future_datetime, futuredatetime + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/date_time/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.FutureDatetime}} + block_example: + fake: FutureDatetime + +Outputs: + + Example(id=1, inline_example=2021-07-07 04:14:42, block_example=2021-07-03 05:52:50) + +#### fake: Iso8601 + +:param tzinfo: timezone, instance of datetime.tzinfo subclass +Example: '2003-10-21T16:05:52+0000' + +Aliases: iso8601 + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/date_time/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.Iso8601}} + block_example: + fake: Iso8601 + +Outputs: + + Example(id=1, inline_example=2003-01-25T19:09:38, block_example=1997-07-22T16:37:16) + +#### fake: Month + +Aliases: month + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/date_time/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.Month}} + block_example: + fake: Month + +Outputs: + + Example(id=1, inline_example=1, block_example=07) + +#### fake: MonthName + +Aliases: month_name, monthname + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/date_time/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.MonthName}} + block_example: + fake: MonthName + +Outputs: + + Example(id=1, inline_example=January, block_example=July) + +#### fake: PastDate + +Get a Date object based on a random date between a given date and 1 day +ago. +Accepts date strings that can be recognized by strtotime(). + +:param start_date Defaults to "-30d" +:param tzinfo: timezone, instance of datetime.tzinfo subclass +Example: DateTime('1999-02-02 11:42:52') +:return DateTime + +Aliases: past_date, pastdate + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/date_time/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.PastDate}} + block_example: + fake: PastDate + +Outputs: + + Example(id=1, inline_example=2021-06-06, block_example=2021-06-02) + +#### fake: PastDatetime + +Get a DateTime object based on a random date between a given date and 1 +second ago. +Accepts date strings that can be recognized by strtotime(). + +:param start_date Defaults to "-30d" +:param tzinfo: timezone, instance of datetime.tzinfo subclass +Example: DateTime('1999-02-02 11:42:52') +:return DateTime + +Aliases: past_datetime, pastdatetime + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/date_time/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.PastDatetime}} + block_example: + fake: PastDatetime + +Outputs: + + Example(id=1, inline_example=2021-06-07 04:14:41, block_example=2021-06-03 05:52:49) + +#### fake: Pytimezone + +Generate a random timezone (see `faker.timezone` for any args) +and return as a python object usable as a `tzinfo` to `datetime` +or other fakers. + +Example: faker.pytimezone() +:return dateutil.tz.tz.tzfile + +Aliases: pytimezone + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/date_time/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.Pytimezone}} + block_example: + fake: Pytimezone + +Outputs: + + Example(id=1, inline_example=tzfile('/usr/share/zoneinfo/Pacific/Funafuti'), block_example=tzfile('/usr/share/zoneinfo/Africa/Khartoum')) + +#### fake: TimeDelta + +Get a timedelta object + +Aliases: time_delta, timedelta + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/date_time/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.TimeDelta}} + block_example: + fake: TimeDelta + +Outputs: + + Example(id=1, inline_example=0:00:00, block_example=0:00:00) + +#### fake: TimeObject + +Get a time object +Example: datetime.time(15, 56, 56, 772876) + +Aliases: time_object, timeobject + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/date_time/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.TimeObject}} + block_example: + fake: TimeObject + +Outputs: + + Example(id=1, inline_example=19:09:38, block_example=16:37:16) + +#### fake: TimeSeries + +Returns a generator yielding tuples of ``(, )``. + +The data points will start at ``start_date``, and be at every time interval specified by +``precision``. +``distrib`` is a callable that accepts ```` and returns ```` + +Aliases: time_series, timeseries + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/date_time/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.TimeSeries}} + block_example: + fake: TimeSeries + +Outputs: + + Example(id=1, inline_example=, block_example=) + +#### fake: Timezone + +Aliases: timezone + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/date_time/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.Timezone}} + block_example: + fake: Timezone + +Outputs: + + Example(id=1, inline_example=Pacific/Funafuti, block_example=Africa/Khartoum) + +#### fake: UnixTime + +Get a timestamp between January 1, 1970 and now, unless passed +explicit start_datetime or end_datetime values. +Example: 1061306726 + +Aliases: unix_time, unixtime + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/date_time/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.UnixTime}} + block_example: + fake: UnixTime + +Outputs: + + Example(id=1, inline_example=1043521778, block_example=869589436) + +### Decorators.Py Fakers + +#### fake: AsciiCompanyEmail + +Aliases: ascii_company_email, asciicompanyemail + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/utils/decorators.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.AsciiCompanyEmail}} + block_example: + fake: AsciiCompanyEmail + +Outputs: + + Example(id=1, inline_example=buckcourtney@tapia.com, block_example=vcrane@moon.com) + +#### fake: AsciiEmail + +Aliases: ascii_email, asciiemail + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/utils/decorators.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.AsciiEmail}} + block_example: + fake: AsciiEmail + +Outputs: + + Example(id=1, inline_example=yodonnell@wiggins.info, block_example=alishawhitehead@gmail.com) + +#### fake: AsciiFreeEmail + +Aliases: ascii_free_email, asciifreeemail + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/utils/decorators.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.AsciiFreeEmail}} + block_example: + fake: AsciiFreeEmail + +Outputs: + + Example(id=1, inline_example=edgar15@yahoo.com, block_example=lovefrances@yahoo.com) + +#### fake: AsciiSafeEmail + +Aliases: ascii_safe_email, asciisafeemail + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/utils/decorators.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.AsciiSafeEmail}} + block_example: + fake: AsciiSafeEmail + +Outputs: + + Example(id=1, inline_example=edgar15@example.com, block_example=lovefrances@example.com) + +#### fake: CompanyEmail + +Aliases: company_email, companyemail + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/utils/decorators.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.CompanyEmail}} + block_example: + fake: CompanyEmail + +Outputs: + + Example(id=1, inline_example=buckcourtney@tapia.com, block_example=vcrane@moon.com) + +#### fake: DomainName + +Produce an Internet domain name with the specified number of +subdomain levels. + +>>> domain_name() +nichols-phillips.com +>>> domain_name(2) +williamson-hopkins.jackson.com + +Aliases: domain_name, domainname + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/utils/decorators.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.DomainName}} + block_example: + fake: DomainName + +Outputs: + + Example(id=1, inline_example=vega.com, block_example=lyons.com) + +#### fake: DomainWord + +Aliases: domain_word, domainword + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/utils/decorators.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.DomainWord}} + block_example: + fake: DomainWord + +Outputs: + + Example(id=1, inline_example=krause-wilcox, block_example=bautista) + +#### fake: FreeEmail + +Aliases: free_email, freeemail + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/utils/decorators.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.FreeEmail}} + block_example: + fake: FreeEmail + +Outputs: + + Example(id=1, inline_example=edgar15@yahoo.com, block_example=lovefrances@yahoo.com) + +#### fake: FreeEmailDomain + +Aliases: free_email_domain, freeemaildomain + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/utils/decorators.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.FreeEmailDomain}} + block_example: + fake: FreeEmailDomain + +Outputs: + + Example(id=1, inline_example=yahoo.com, block_example=yahoo.com) + +#### fake: Hostname + +Produce a hostname with specified number of subdomain levels. + +>>> hostname() +db-01.nichols-phillips.com +>>> hostname(0) +laptop-56 +>>> hostname(2) +web-12.williamson-hopkins.jackson.com + +Aliases: hostname + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/utils/decorators.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.Hostname}} + block_example: + fake: Hostname + +Outputs: + + Example(id=1, inline_example=lt-77.fowler.net, block_example=db-16.tapia.com) + +#### fake: SafeDomainName + +Aliases: safe_domain_name, safedomainname + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/utils/decorators.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.SafeDomainName}} + block_example: + fake: SafeDomainName + +Outputs: + + Example(id=1, inline_example=example.com, block_example=example.com) + +#### fake: SafeEmail + +Aliases: safe_email, safeemail + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/utils/decorators.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.SafeEmail}} + block_example: + fake: SafeEmail + +Outputs: + + Example(id=1, inline_example=edgar15@example.com, block_example=lovefrances@example.com) + +#### fake: Slug + +Django algorithm + +Aliases: slug + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/utils/decorators.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.Slug}} + block_example: + fake: Slug + +Outputs: + + Example(id=1, inline_example=discover-mother, block_example=father-challenge) + +### File Fakers + +#### fake: FileExtension + +Generate a file extension under the specified ``category``. + +If ``category`` is ``None``, a random category will be used. The list of +valid categories include: ``'audio'``, ``'image'``, ``'office'``, +``'text'``, and ``'video'``. + +Aliases: file_extension, fileextension + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/file/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.FileExtension}} + block_example: + fake: FileExtension + +Outputs: + + Example(id=1, inline_example=js, block_example=ods) + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.FileExtension(category='image')}} + block_example: + fake.FileExtension: + category: image + +Outputs: + + Example(id=1, inline_example=jpeg, block_example=png) + +#### fake: FileName + +Generate a random file name with extension. + +If ``extension`` is ``None``, a random extension will be created under +the hood using |file_extension| with the specified ``category``. If a +value for ``extension`` is provided, the value will be used instead, +and ``category`` will be ignored. The actual name part itself is +generated using |word|. + +:sample size=10: + +Aliases: file_name, filename + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/file/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.FileName}} + block_example: + fake: FileName + +Outputs: + + Example(id=1, inline_example=much.mp3, block_example=why.js) + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.FileName(category='audio')}} + block_example: + fake.FileName: + category: audio + +Outputs: + + Example(id=1, inline_example=me.mp3, block_example=past.mp3) + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.FileName(extension='abcdef')}} + block_example: + fake.FileName: + extension: abcdef + +Outputs: + + Example(id=1, inline_example=wait.abcdef, block_example=whatever.abcdef) + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.FileName(category='audio', extension='abcdef')}} + block_example: + fake.FileName: + category: audio + extension: abcdef + +Outputs: + + Example(id=1, inline_example=discover.abcdef, block_example=mother.abcdef) + +#### fake: FilePath + +Generate an absolute pathname to a file. + +This method uses |file_name| under the hood to generate the file name +itself, and ``depth`` controls the depth of the directory path, and +|word| is used under the hood to generate the different directory names. + +:sample size=10: + +Aliases: file_path, filepath + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/file/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.FilePath}} + block_example: + fake: FilePath + +Outputs: + + Example(id=1, inline_example=/bit/force.avi, block_example=/marriage/give.wav) + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.FilePath(depth=3)}} + block_example: + fake.FilePath: + depth: 3 + +Outputs: + + Example(id=1, inline_example=/popular/four/leader/health.mp4, block_example=/near/tree/level/me.png) + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.FilePath(depth=5, category='video')}} + block_example: + fake.FilePath: + depth: 5 + category: video + +Outputs: + + Example(id=1, inline_example=/address/whole/official/why/support/assume.mov, block_example=/still/thank/see/inside/though/serve.mp4) + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.FilePath(depth=5, category='video', extension='abcdef')}} + block_example: + fake.FilePath: + depth: 5 + category: video + extension: abcdef + +Outputs: + + Example(id=1, inline_example=/their/minute/population/ability/process/relate.abcdef, block_example=/score/gas/show/either/goal/trip.abcdef) + +#### fake: MimeType + +Generate a mime type under the specified ``category``. + +If ``category`` is ``None``, a random category will be used. The list of +valid categories include ``'application'``, ``'audio'``, ``'image'``, +``'message'``, ``'model'``, ``'multipart'``, ``'text'``, and +``'video'``. + +Aliases: mime_type, mimetype + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/file/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.MimeType}} + block_example: + fake: MimeType + +Outputs: + + Example(id=1, inline_example=video/x-ms-wmv, block_example=model/vrml) + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.MimeType(category='application')}} + block_example: + fake.MimeType: + category: application + +Outputs: + + Example(id=1, inline_example=application/rss+xml, block_example=application/gzip) + +#### fake: UnixDevice + +Generate a Unix device file name. + +If ``prefix`` is ``None``, a random prefix will be used. The list of +valid prefixes include: ``'sd'``, ``'vd'``, and ``'xvd'``. + +Aliases: unix_device, unixdevice + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/file/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.UnixDevice}} + block_example: + fake: UnixDevice + +Outputs: + + Example(id=1, inline_example=/dev/xvdp, block_example=/dev/vdz) + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.UnixDevice(prefix='mmcblk')}} + block_example: + fake.UnixDevice: + prefix: mmcblk + +Outputs: + + Example(id=1, inline_example=/dev/mmcblkj, block_example=/dev/mmcblkp) + +#### fake: UnixPartition + +Generate a Unix partition name. + +This method uses |unix_device| under the hood to create a device file +name with the specified ``prefix``. + +Aliases: unix_partition, unixpartition + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/file/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.UnixPartition}} + block_example: + fake: UnixPartition + +Outputs: + + Example(id=1, inline_example=/dev/xvdg8, block_example=/dev/sdj2) + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.UnixPartition(prefix='mmcblk')}} + block_example: + fake.UnixPartition: + prefix: mmcblk + +Outputs: + + Example(id=1, inline_example=/dev/mmcblky1, block_example=/dev/mmcblkt4) + +### Geo Fakers + +#### fake: Coordinate + +Optionally center the coord and pick a point within radius. + +Aliases: coordinate + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/geo/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.Coordinate}} + block_example: + fake: Coordinate + +Outputs: + + Example(id=1, inline_example=80.880444, block_example=37.397359) + +#### fake: Latitude + +Aliases: latitude + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/geo/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.Latitude}} + block_example: + fake: Latitude + +Outputs: + + Example(id=1, inline_example=40.440222, block_example=18.6986795) + +#### fake: Latlng + +Aliases: latlng + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/geo/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.Latlng}} + block_example: + fake: Latlng + +Outputs: + + Example(id=1, inline_example=(Decimal('66.6004235'), Decimal('-62.724453')), block_example=(Decimal('45.475847'), Decimal('-105.227997'))) + +#### fake: LocalLatlng + +Returns a location known to exist on land in a country specified by `country_code`. +Defaults to 'en_US'. See the `land_coords` list for available locations/countries. + +Aliases: local_latlng, locallatlng + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/geo/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.LocalLatlng}} + block_example: + fake: LocalLatlng + +Outputs: + + Example(id=1, inline_example=('33.03699', '-117.29198', 'Encinitas', 'US', 'America/Los_Angeles'), block_example=('41.0051', '-73.78458', 'Scarsdale', 'US', 'America/New_York')) + +#### fake: LocationOnLand + +Returns a random tuple specifying a coordinate set guaranteed to exist on land. +Format is `(latitude, longitude, place name, two-letter country code, timezone)` +Pass `coords_only` to return coordinates without metadata. + +Aliases: location_on_land, locationonland + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/geo/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.LocationOnLand}} + block_example: + fake: LocationOnLand + +Outputs: + + Example(id=1, inline_example=('43.4125', '23.225', 'Montana', 'BG', 'Europe/Sofia'), block_example=('65.84811', '24.14662', 'Tornio', 'FI', 'Europe/Helsinki')) + +#### fake: Longitude + +Aliases: longitude + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/geo/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.Longitude}} + block_example: + fake: Longitude + +Outputs: + + Example(id=1, inline_example=80.880444, block_example=37.397359) + +### Internet Fakers + +#### fake: Dga + +Generates a domain name by given date +https://en.wikipedia.org/wiki/Domain_generation_algorithm + +:type year: int +:type month: int +:type day: int +:type tld: str +:type length: int +:rtype: str + +Aliases: dga + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/internet/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.Dga}} + block_example: + fake: Dga + +Outputs: + + Example(id=1, inline_example=rirpbubretascqucvnrhbyydewtmalpjievdbixsxknwnwelialvretierm.com, block_example=fctbfriciqlcbvrqhfsxrotu.com) + +#### fake: HttpMethod + +Returns random HTTP method +https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods + +:rtype: str + +Aliases: http_method, httpmethod + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/internet/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.HttpMethod}} + block_example: + fake: HttpMethod + +Outputs: + + Example(id=1, inline_example=TRACE, block_example=OPTIONS) + +#### fake: ImageUrl + +Returns URL to placeholder image +Example: http://placehold.it/640x480 + +Aliases: image_url, imageurl + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/internet/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.ImageUrl}} + block_example: + fake: ImageUrl + +Outputs: + + Example(id=1, inline_example=https://www.lorempixel.com/300/635, block_example=https://placeimg.com/151/676/any) + +#### fake: Ipv4 + +Returns a random IPv4 address or network with a valid CIDR. + +:param network: Network address +:param address_class: IPv4 address class (a, b, or c) +:param private: Public or private +:returns: IPv4 + +Aliases: ipv4 + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/internet/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.Ipv4}} + block_example: + fake: Ipv4 + +Outputs: + + Example(id=1, inline_example=12.130.104.103, block_example=70.17.181.9) + +#### fake: Ipv4NetworkClass + +Returns a IPv4 network class 'a', 'b' or 'c'. + +:returns: IPv4 network class + +Aliases: ipv4_network_class, ipv4networkclass + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/internet/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.Ipv4NetworkClass}} + block_example: + fake: Ipv4NetworkClass + +Outputs: + + Example(id=1, inline_example=b, block_example=b) + +#### fake: Ipv4Private + +Returns a private IPv4. + +:param network: Network address +:param address_class: IPv4 address class (a, b, or c) +:returns: Private IPv4 + +Aliases: ipv4_private, ipv4private + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/internet/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.Ipv4Private}} + block_example: + fake: Ipv4Private + +Outputs: + + Example(id=1, inline_example=10.128.66.93, block_example=192.168.75.62) + +#### fake: Ipv4Public + +Returns a public IPv4 excluding private blocks. + +:param network: Network address +:param address_class: IPv4 address class (a, b, or c) +:returns: Public IPv4 + +Aliases: ipv4_public, ipv4public + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/internet/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.Ipv4Public}} + block_example: + fake: Ipv4Public + +Outputs: + + Example(id=1, inline_example=48.8.75.189, block_example=198.165.159.67) + +#### fake: Ipv6 + +Produce a random IPv6 address or network with a valid CIDR + +Aliases: ipv6 + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/internet/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.Ipv6}} + block_example: + fake: Ipv6 + +Outputs: + + Example(id=1, inline_example=23a7:711a:8133:2876:37eb:dcda:e87a:1613, block_example=1846:d424:c17c:6279:23c6:6130:4826:8673) + +#### fake: MacAddress + +Aliases: mac_address, macaddress + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/internet/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.MacAddress}} + block_example: + fake: MacAddress + +Outputs: + + Example(id=1, inline_example=07:2f:cc:00:fc:aa, block_example=7c:a6:20:61:71:7a) + +#### fake: PortNumber + +Returns a network port number +https://tools.ietf.org/html/rfc6335 + +:param is_system: System or well-known ports +:param is_user: User or registered ports +:param is_dynamic: Dynamic / private / ephemeral ports +:rtype: int + +Aliases: port_number, portnumber + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/internet/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.PortNumber}} + block_example: + fake: PortNumber + +Outputs: + + Example(id=1, inline_example=53075, block_example=39755) + +#### fake: Tld + +Aliases: tld + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/internet/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.Tld}} + block_example: + fake: Tld + +Outputs: + + Example(id=1, inline_example=info, block_example=biz) + +#### fake: Uri + +Aliases: uri + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/internet/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.Uri}} + block_example: + fake: Uri + +Outputs: + + Example(id=1, inline_example=http://www.harding.info/home/, block_example=https://lowe.com/) + +#### fake: UriExtension + +Aliases: uri_extension, uriextension + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/internet/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.UriExtension}} + block_example: + fake: UriExtension + +Outputs: + + Example(id=1, inline_example=.jsp, block_example=.php) + +#### fake: UriPage + +Aliases: uri_page, uripage + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/internet/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.UriPage}} + block_example: + fake: UriPage + +Outputs: + + Example(id=1, inline_example=post, block_example=login) + +#### fake: UriPath + +Aliases: uri_path, uripath + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/internet/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.UriPath}} + block_example: + fake: UriPath + +Outputs: + + Example(id=1, inline_example=main, block_example=posts/explore/categories) + +#### fake: Url + +:param schemes: a list of strings to use as schemes, one will chosen randomly. +If None, it will generate http and https urls. +Passing an empty list will result in schemeless url generation like "://domain.com". + +:returns: a random url string. + +Aliases: url + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/internet/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.Url}} + block_example: + fake: Url + +Outputs: + + Example(id=1, inline_example=https://fowler.net/, block_example=http://www.huber.com/) + +### Isbn Fakers + +#### fake: Isbn10 + +Aliases: isbn10 + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/isbn/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.Isbn10}} + block_example: + fake: Isbn10 + +Outputs: + + Example(id=1, inline_example=1-115-87148-X, block_example=0-85839-894-X) + +#### fake: Isbn13 + +Aliases: isbn13 + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/isbn/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.Isbn13}} + block_example: + fake: Isbn13 + +Outputs: + + Example(id=1, inline_example=978-1-115-87148-8, block_example=978-0-85839-894-8) + +### Job Fakers + +#### fake: Job + +Aliases: job + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/job/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.Job}} + block_example: + fake: Job + +Outputs: + + Example(id=1, inline_example=Radiographer, diagnostic, block_example=Ophthalmologist) + +### Lorem Fakers + +#### fake: Paragraphs + +Generate a list of paragraphs. + +This method uses |paragraph| under the hood to generate paragraphs, and +the ``nb`` argument controls exactly how many sentences the list will +contain. The ``ext_word_list`` argument works in exactly the same way +as well. + +Aliases: paragraphs + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/lorem/__init__.py) + +#### fake: Sentences + +Generate a list of sentences. + +This method uses |sentence| under the hood to generate sentences, and +the ``nb`` argument controls exactly how many sentences the list will +contain. The ``ext_word_list`` argument works in exactly the same way +as well. + +Aliases: sentences + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/lorem/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.Sentences}} + block_example: + fake: Sentences + +Outputs: + + Example(id=1, inline_example=['Bring TV program actually race.', 'Themselves true power home price check real.', 'Score from animal exactly drive well good.'], block_example=['Pull opportunity throughout take car.', 'Hold increase practice ability court.', 'Civil development large report purpose themselves.']) + +#### fake: Texts + +Generate a list of text strings. + +The ``nb_texts`` argument controls how many text strings the list will +contain, and this method uses |text| under the hood for text generation, +so the two remaining arguments, ``max_nb_chars`` and ``ext_word_list`` +will work in exactly the same way as well. + + + +ext_word_list=['abc', 'def', 'ghi', 'jkl'] + +Aliases: texts + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/lorem/__init__.py) + +#### fake: Words + +Generate a tuple of words. + +The ``nb`` argument controls the number of words in the resulting list, +and if ``ext_word_list`` is provided, words from that list will be used +instead of those from the locale provider's built-in word list. + +If ``unique`` is ``True``, this method will return a list containing +unique words. Under the hood, |random_sample| will be used for sampling +without replacement. If ``unique`` is ``False``, |random_choices| is +used instead, and the list returned may contain duplicates. + +.. warning:: +Depending on the length of a locale provider's built-in word list or +on the length of ``ext_word_list`` if provided, a large ``nb`` can +exhaust said lists if ``unique`` is ``True``, raising an exception. + +Aliases: words + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/lorem/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.Words}} + block_example: + fake: Words + +Outputs: + + Example(id=1, inline_example=['together', 'range', 'line'], block_example=['beyond', 'its', 'particularly']) + +### Misc Fakers + +#### fake: Binary + +Generate a random binary blob of ``length`` bytes. + +Aliases: binary + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/misc/__init__.py) + +#### fake: Boolean + +Generate a random boolean value based on ``chance_of_getting_true``. + +:sample size=10: chance_of_getting_true=25 +:sample size=10: chance_of_getting_true=50 +:sample size=10: chance_of_getting_true=75 + +Aliases: boolean + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/misc/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.Boolean(chance_of_getting_true=25)}} + block_example: + fake.Boolean: + chance_of_getting_true: 25 + +Outputs: + + Example(id=1, inline_example=False, block_example=0) + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.Boolean(chance_of_getting_true=50)}} + block_example: + fake.Boolean: + chance_of_getting_true: 50 + +Outputs: + + Example(id=1, inline_example=True, block_example=0) + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.Boolean(chance_of_getting_true=75)}} + block_example: + fake.Boolean: + chance_of_getting_true: 75 + +Outputs: + + Example(id=1, inline_example=True, block_example=1) + +#### fake: Csv + +Generate random comma-separated values. + +For more information on the different arguments of this method, please refer to +:meth:`dsv() ` which is used under the hood. + + +data_columns=('{{name}}', '{{address}}', '{{safe_color_name}}'), +num_rows=10, include_row_ids=True + +Aliases: csv + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/misc/__init__.py) + +#### fake: Dsv + +Generate random delimiter-separated values. + +This method's behavior share some similarities with ``csv.writer``. The ``dialect`` and +``**fmtparams`` arguments are the same arguments expected by ``csv.writer`` to control its +behavior, and instead of expecting a file-like object to where output will be written, the +output is controlled by additional keyword arguments and is returned as a string. + +The ``dialect`` argument defaults to ``'faker-csv'`` which is the name of a ``csv.excel`` +subclass with full quoting enabled. + +The ``header`` argument expects a list or a tuple of strings that will serve as the header row +if supplied. The ``data_columns`` argument expects a list or a tuple of string tokens, and these +string tokens will be passed to :meth:`pystr_format() ` +for data generation. Argument Groups are used to pass arguments to the provider methods. +Both ``header`` and ``data_columns`` must be of the same length. + +Example: +fake.set_arguments('top_half', {'min_value': 50, 'max_value': 100}) +fake.dsv(data_columns=('{{ name }}', '{{ pyint:top_half }}')) + +The ``num_rows`` argument controls how many rows of data to generate, and the ``include_row_ids`` +argument may be set to ``True`` to include a sequential row ID column. + +Aliases: dsv + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/misc/__init__.py) + +#### fake: FixedWidth + +Generate random fixed width values. + +Using a list of tuple records that is passed as ``data_columns``, that +defines the structure that will be generated. Arguments within the +record are provider specific, and should be a dictionary that will be +passed to the provider method. + +Data Column List format +[('field width', 'definition', {'arguments'})] + +The definition can be 'provider', 'provider:argument_group', tokenized +'string {{ provider:argument_group }}' that is passed to the python +provider method pystr_format() for generation, or a fixed '@word'. +Using Lists, Tuples, and Dicts as a definition for structure. + +Argument Groups can be used to pass arguments to the provider methods, +but will override the arguments supplied in the tuple record. + +Example: +fake.set_arguments('top_half', {'min_value': 50, 'max_value': 100}) +fake.fixed_width(data_columns=[(20, 'name'), (3, 'pyint:top_half')]) + +:param data_columns: specification for the data structure +:type data_columns: list +:param num_rows: number of rows the generator will yield +:type num_rows: int +:param align: positioning of the value. (left, middle, right) +:type align: str +:return: Serialized Fixed Width data +:rtype: str + +'max_value': 100})], align='right', num_rows=2 + +Aliases: fixed_width, fixedwidth + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/misc/__init__.py) + +#### fake: Json + +Generate random JSON structure values. + +Using a dictionary or list of records that is passed as ``data_columns``, +define the structure that is used to build JSON structures. For complex +data structures it is recommended to use the dictionary format. + +Data Column Dictionary format: +{'key name': 'definition'} + +The definition can be 'provider', 'provider:argument_group', tokenized +'string {{ provider:argument_group }}' that is passed to the python +provider method pystr_format() for generation, or a fixed '@word'. +Using Lists, Tuples, and Dicts as a definition for structure. + +Example: +fake.set_arguments('top_half', {'min_value': 50, 'max_value': 100}) +fake.json(data_columns={'Name': 'name', 'Score': 'pyint:top_half'}) + +Data Column List format: +[('key name', 'definition', {'arguments'})] + +With the list format the definition can be a list of records, to create +a list within the structure data. For literal entries within the list, +set the 'field_name' to None. + +:param data_columns: specification for the data structure +:type data_columns: dict +:param num_rows: number of rows the returned +:type num_rows: int +:param indent: number of spaces to indent the fields +:type indent: int +:return: Serialized JSON data +:rtype: str + +'Details': {'Name': 'name', 'Address': 'address'}}, num_rows=2 + +num_rows=1 + +{'min_value': 50, 'max_value': 100})], num_rows=1 + +Aliases: json + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/misc/__init__.py) + +#### fake: Md5 + +Generate a random MD5 hash. + +If ``raw_output`` is ``False`` (default), a hexadecimal string representation of the MD5 hash +will be returned. If ``True``, a ``bytes`` object representation will be returned instead. + +Aliases: md5 + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/misc/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.Md5(raw_output=False)}} + block_example: + fake.Md5: + raw_output: false + +Outputs: + + Example(id=1, inline_example=0ced544422ae9d74b425752334506cb5, block_example=e2e862d8792e2235570eb2eb93f0b720) + +#### fake: NullBoolean + +Generate ``None``, ``True``, or ``False``, each with equal probability. + +:sample size=15: + +Aliases: null_boolean, nullboolean + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/misc/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.NullBoolean}} + block_example: + fake: NullBoolean + +Outputs: + + Example(id=1, inline_example=False, block_example=False) + +#### fake: Password + +Generate a random password of the specified ``length``. + +The arguments ``special_chars``, ``digits``, ``upper_case``, and ``lower_case`` control +what category of characters will appear in the generated password. If set to ``True`` +(default), at least one character from the corresponding category is guaranteed to appear. +Special characters are characters from ``!@#$%^&*()_+``, digits are characters from +``0123456789``, and uppercase and lowercase characters are characters from the ASCII set of +letters. + +Aliases: password + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/misc/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.Password(length=12)}} + block_example: + fake.Password: + length: 12 + +Outputs: + + Example(id=1, inline_example=z(1Bef!mR*(X, block_example=@tlUcamZ*+6$) + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.Password(length=40, special_chars=False, upper_case=False)}} + block_example: + fake.Password: + length: 40 + special_chars: false + upper_case: false + +Outputs: + + Example(id=1, inline_example=xw1qpnplndj7l05cspcm15zaejah816i2ebe3whu, block_example=pfaqwxddz723q20eighlofdz9rfc2vpwgo4e71y7) + +#### fake: Psv + +Generate random pipe-separated values. + +For more information on the different arguments of this method, please refer to +:meth:`dsv() ` which is used under the hood. + + +data_columns=('{{name}}', '{{address}}', '{{safe_color_name}}'), +num_rows=10, include_row_ids=True + +Aliases: psv + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/misc/__init__.py) + +#### fake: Sha1 + +Generate a random SHA1 hash. + +If ``raw_output`` is ``False`` (default), a hexadecimal string representation of the SHA1 hash +will be returned. If ``True``, a ``bytes`` object representation will be returned instead. + +Aliases: sha1 + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/misc/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.Sha1(raw_output=False)}} + block_example: + fake.Sha1: + raw_output: false + +Outputs: + + Example(id=1, inline_example=c6b69eb0fa28e2085eee479bb87f7bdfcee2e3b4, block_example=f57a6cb25f89722d7389101a0ef9f9547930c529) + +#### fake: Sha256 + +Generate a random SHA256 hash. + +If ``raw_output`` is ``False`` (default), a hexadecimal string representation of the SHA56 hash +will be returned. If ``True``, a ``bytes`` object representation will be returned instead. + +Aliases: sha256 + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/misc/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.Sha256(raw_output=False)}} + block_example: + fake.Sha256: + raw_output: false + +Outputs: + + Example(id=1, inline_example=faa5be1206846743dec0c4d3e5afc2d48a023011fdb6eabcc842f2b47eca8a00, block_example=8e36506d1af0f8133ec6c833feb77689049fec2a0f7a49b8218fd49f41fde9d9) + +#### fake: Tar + +Generate a bytes object containing a random valid tar file. + +The number and sizes of files contained inside the resulting archive can be controlled +using the following arguments: + +- ``uncompressed_size`` - the total size of files before compression, 16 KiB by default +- ``num_files`` - the number of files archived in resulting zip file, 1 by default +- ``min_file_size`` - the minimum size of each file before compression, 4 KiB by default + +No compression is used by default, but setting ``compression`` to one of the values listed +below will use the corresponding compression type. + +- ``'bzip2'`` or ``'bz2'`` for BZIP2 +- ``'lzma'`` or ``'xz'`` for LZMA +- ``'gzip'`` or ``'gz'`` for GZIP + +Aliases: tar + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/misc/__init__.py) + +#### fake: Tsv + +Generate random tab-separated values. + +For more information on the different arguments of this method, please refer to +:meth:`dsv() ` which is used under the hood. + + +data_columns=('{{name}}', '{{address}}', '{{safe_color_name}}'), +num_rows=10, include_row_ids=True + +Aliases: tsv + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/misc/__init__.py) + +#### fake: Uuid4 + +Generate a random UUID4 object and cast it to another type if specified using a callable ``cast_to``. + +By default, ``cast_to`` is set to ``str``. + +May be called with ``cast_to=None`` to return a full-fledged ``UUID``. + +Aliases: uuid4 + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/misc/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.Uuid4}} + block_example: + fake: Uuid4 + +Outputs: + + Example(id=1, inline_example=23a7711a-8133-4876-b7eb-dcd9e87a1613, block_example=1846d424-c17c-4279-a3c6-612f48268673) + +#### fake: Zip + +Generate a bytes object containing a random valid zip archive file. + +The number and sizes of files contained inside the resulting archive can be controlled +using the following arguments: + +- ``uncompressed_size`` - the total size of files before compression, 16 KiB by default +- ``num_files`` - the number of files archived in resulting zip file, 1 by default +- ``min_file_size`` - the minimum size of each file before compression, 4 KiB by default + +No compression is used by default, but setting ``compression`` to one of the values listed +below will use the corresponding compression type. + +- ``'bzip2'`` or ``'bz2'`` for BZIP2 +- ``'lzma'`` or ``'xz'`` for LZMA +- ``'deflate'``, ``'gzip'``, or ``'gz'`` for GZIP + +Aliases: zip + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/misc/__init__.py) + +### Person Fakers + +#### fake: LanguageName + +Generate a random i18n language name (e.g. English). + +Aliases: language_name, languagename + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/person/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.LanguageName}} + block_example: + fake: LanguageName + +Outputs: + + Example(id=1, inline_example=Ossetian, block_example=Macedonian) + +#### fake: LastNameFemale + +Aliases: last_name_female, lastnamefemale + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/person/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.LastNameFemale}} + block_example: + fake: LastNameFemale + +Outputs: + + Example(id=1, inline_example=Goodwin, block_example=Hendrix) + +#### fake: LastNameMale + +Aliases: last_name_male, lastnamemale + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/person/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.LastNameMale}} + block_example: + fake: LastNameMale + +Outputs: + + Example(id=1, inline_example=Goodwin, block_example=Hendrix) + +#### fake: LastNameNonbinary + +Aliases: last_name_nonbinary, lastnamenonbinary + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/person/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.LastNameNonbinary}} + block_example: + fake: LastNameNonbinary + +Outputs: + + Example(id=1, inline_example=Goodwin, block_example=Hendrix) + +#### fake: NameNonbinary + +Aliases: name_nonbinary, namenonbinary + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/person/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.NameNonbinary}} + block_example: + fake: NameNonbinary + +Outputs: + + Example(id=1, inline_example=Lydia Escobar III, block_example=Edgar Moon II) + +#### fake: Prefix + +Aliases: prefix + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/person/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.Prefix}} + block_example: + fake: Prefix + +Outputs: + + Example(id=1, inline_example=Mr., block_example=Ms.) + +#### fake: PrefixFemale + +Aliases: prefix_female, prefixfemale + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/person/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.PrefixFemale}} + block_example: + fake: PrefixFemale + +Outputs: + + Example(id=1, inline_example=Dr., block_example=Miss) + +#### fake: PrefixMale + +Aliases: prefix_male, prefixmale + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/person/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.PrefixMale}} + block_example: + fake: PrefixMale + +Outputs: + + Example(id=1, inline_example=Dr., block_example=Dr.) + +#### fake: PrefixNonbinary + +Aliases: prefix_nonbinary, prefixnonbinary + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/person/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.PrefixNonbinary}} + block_example: + fake: PrefixNonbinary + +Outputs: + + Example(id=1, inline_example=Dr., block_example=Misc.) + +#### fake: Suffix + +Aliases: suffix + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/person/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.Suffix}} + block_example: + fake: Suffix + +Outputs: + + Example(id=1, inline_example=DVM, block_example=V) + +#### fake: SuffixFemale + +Aliases: suffix_female, suffixfemale + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/person/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.SuffixFemale}} + block_example: + fake: SuffixFemale + +Outputs: + + Example(id=1, inline_example=DVM, block_example=PhD) + +#### fake: SuffixMale + +Aliases: suffix_male, suffixmale + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/person/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.SuffixMale}} + block_example: + fake: SuffixMale + +Outputs: + + Example(id=1, inline_example=DDS, block_example=V) + +#### fake: SuffixNonbinary + +Aliases: suffix_nonbinary, suffixnonbinary + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/person/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.SuffixNonbinary}} + block_example: + fake: SuffixNonbinary + +Outputs: + + Example(id=1, inline_example=DDS, block_example=V) + +### Phone_Number Fakers + +#### fake: CountryCallingCode + +Aliases: country_calling_code, countrycallingcode + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/phone_number/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.CountryCallingCode}} + block_example: + fake: CountryCallingCode + +Outputs: + + Example(id=1, inline_example=+386, block_example=+1 670) + +#### fake: Msisdn + +https://en.wikipedia.org/wiki/MSISDN + +Aliases: msisdn + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/phone_number/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.Msisdn}} + block_example: + fake: Msisdn + +Outputs: + + Example(id=1, inline_example=9894719659342, block_example=2094711220186) + +### Profile Fakers + +#### fake: Profile + +Generates a complete profile. +If "fields" is not empty, only the fields in the list will be returned + +Aliases: profile + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/profile/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.Profile}} + block_example: + fake: Profile + +Outputs: + + Example(id=1, inline_example={'job': 'Chartered loss adjuster', 'company': 'Landry Inc', 'ssn': '203-96-3622', 'residence': '16884 Mcgrath Overpass Apt. 615\nWest Paula, GA 57022', 'current_location': (Decimal('-38.4751525'), Decimal('12.479165')), 'blood_group': 'A-', 'website': ['http://johnston.biz/'], 'username': 'erikduncan', 'name': 'Mr. Eugene Pitts', 'sex': 'M', 'address': 'Unit 6582 Box 1972\nDPO AP 53704', 'mail': 'hnovak@yahoo.com', 'birthdate': datetime.date(1997, 11, 26)}, block_example={'job': 'IT trainer', 'company': 'Lamb-Walter', 'ssn': '687-26-8894', 'residence': 'PSC 0555, Box 0824\nAPO AP 20935', 'current_location': (Decimal('11.7384085'), Decimal('132.967921')), 'blood_group': 'AB+', 'website': ['http://www.church.com/', 'http://www.leonard.info/', 'https://www.church.info/', 'https://shepherd.com/'], 'username': 'yrubio', 'name': 'Ms. Jade Poole DVM', 'sex': 'F', 'address': 'Unit 9930 Box 0248\nDPO AP 33853', 'mail': 'curtis74@yahoo.com', 'birthdate': datetime.date(2010, 8, 1)}) + +#### fake: SimpleProfile + +Generates a basic profile with personal informations + +Aliases: simple_profile, simpleprofile + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/profile/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.SimpleProfile}} + block_example: + fake: SimpleProfile + +Outputs: + + Example(id=1, inline_example={'username': 'gkane', 'name': 'Tammie Harris', 'sex': 'F', 'address': 'USS George\nFPO AE 85294', 'mail': 'becky62@gmail.com', 'birthdate': datetime.date(1973, 12, 28)}, block_example={'username': 'qberry', 'name': 'Trevor Patterson', 'sex': 'M', 'address': 'USCGC Sosa\nFPO AP 22707', 'mail': 'colinhurley@hotmail.com', 'birthdate': datetime.date(1926, 12, 24)}) + +### Providers Fakers + +#### fake: Bothify + +Generate a string with each placeholder in ``text`` replaced according +to the following rules: + +- Number signs ('#') are replaced with a random digit (0 to 9). +- Question marks ('?') are replaced with a random character from ``letters``. + +By default, ``letters`` contains all ASCII letters, uppercase and lowercase. + +Under the hood, this method uses :meth:`numerify() ` and +and :meth:`lexify() ` to generate random values for number +signs and question marks respectively. + +Aliases: bothify + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.Bothify(letters='ABCDE')}} + block_example: + fake.Bothify: + letters: ABCDE + +Outputs: + + Example(id=1, inline_example=58 DA, block_example=48 CA) + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: '${{fake.Bothify(text=''Product Number: ????-########'')}}' + block_example: + fake.Bothify: + text: 'Product Number: ????-########' + +Outputs: + + Example(id=1, inline_example=Product Number: CfMZ-85839894, block_example=Product Number: cNQq-65934232) + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: '${{fake.Bothify(text=''Product Number: ????-########'', letters=''ABCDE'')}}' + block_example: + fake.Bothify: + text: 'Product Number: ????-########' + letters: ABCDE + +Outputs: + + Example(id=1, inline_example=Product Number: DECE-71122018, block_example=Product Number: CACE-33969477) + +#### fake: Hexify + +Generate a string with each circumflex ('^') in ``text`` +replaced with a random hexadecimal character. + +By default, ``upper`` is set to False. If set to ``True``, output +will be formatted using uppercase hexadecimal characters. + +Aliases: hexify + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: '${{fake.Hexify(text=''MAC Address: ^^:^^:^^:^^:^^:^^'')}}' + block_example: + fake.Hexify: + text: 'MAC Address: ^^:^^:^^:^^:^^:^^' + +Outputs: + + Example(id=1, inline_example=MAC Address: 95:65:18:f2:24:41, block_example=MAC Address: 2c:87:6d:8e:fb:2a) + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: '${{fake.Hexify(text=''MAC Address: ^^:^^:^^:^^:^^:^^'', upper=True)}}' + block_example: + fake.Hexify: + text: 'MAC Address: ^^:^^:^^:^^:^^:^^' + upper: true + +Outputs: + + Example(id=1, inline_example=MAC Address: 3F:A6:70:83:7B:5A, block_example=MAC Address: D1:34:71:20:36:3C) + +#### fake: LanguageCode + +Generate a random i18n language code (e.g. en). + +Aliases: language_code, languagecode + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.LanguageCode}} + block_example: + fake: LanguageCode + +Outputs: + + Example(id=1, inline_example=pap, block_example=mn) + +#### fake: Lexify + +Generate a string with each question mark ('?') in ``text`` +replaced with a random character from ``letters``. + +By default, ``letters`` contains all ASCII letters, uppercase and lowercase. + +Aliases: lexify + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: '${{fake.Lexify(text=''Random Identifier: ??????????'')}}' + block_example: + fake.Lexify: + text: 'Random Identifier: ??????????' + +Outputs: + + Example(id=1, inline_example=Random Identifier: TemKopZjZI, block_example=Random Identifier: CffuGFgtJs) + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: '${{fake.Lexify(text=''Random Identifier: ??????????'', letters=''ABCDE'')}}' + block_example: + fake.Lexify: + text: 'Random Identifier: ??????????' + letters: ABCDE + +Outputs: + + Example(id=1, inline_example=Random Identifier: AECEBEEECD, block_example=Random Identifier: AEDCEBCBBB) + +#### fake: Locale + +Generate a random underscored i18n locale code (e.g. en_US). + +Aliases: locale + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.Locale}} + block_example: + fake: Locale + +Outputs: + + Example(id=1, inline_example=sw_KE, block_example=raj_IN) + +#### fake: Numerify + +Generate a string with each placeholder in ``text`` replaced according +to the following rules: + +- Number signs ('#') are replaced with a random digit (0 to 9). +- Percent signs ('%') are replaced with a random non-zero digit (1 to 9). +- Exclamation marks ('!') are replaced with a random digit or an empty string. +- At symbols ('@') are replaced with a random non-zero digit or an empty string. + +Under the hood, this method uses :meth:`random_digit() `, +:meth:`random_digit_not_null() `, +:meth:`random_digit_or_empty() `, +and :meth:`random_digit_not_null_or_empty() ` +to generate the random values. + +Aliases: numerify + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.Numerify(text='Intel Core i%-%%##K vs AMD Ryzen % %%##X')}} + block_example: + fake.Numerify: + text: Intel Core i%-%%##K vs AMD Ryzen % %%##X + +Outputs: + + Example(id=1, inline_example=Intel Core i6-3575K vs AMD Ryzen 7 7294X, block_example=Intel Core i3-4409K vs AMD Ryzen 8 7735X) + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.Numerify(text='!!! !!@ !@! !@@ @!! @!@ @@! @@@')}} + block_example: + fake.Numerify: + text: '!!! !!@ !@! !@@ @!! @!@ @@! @@@' + +Outputs: + + Example(id=1, inline_example=90 1 248 8 751 7 , block_example=4 61 7 926 81 6) + +#### fake: RandomChoices + +Generate a list of objects randomly sampled from ``elements`` with replacement. + +For information on the ``elements`` and ``length`` arguments, please refer to +:meth:`random_elements() ` which +is used under the hood with the ``unique`` argument explicitly set to ``False``. + + + +("a", 0.45), +("b", 0.35), +("c", 0.15), +("d", 0.05), +]) + +("a", 0.45), +("b", 0.35), +("c", 0.15), +("d", 0.05), +]), length=20 + +Aliases: random_choices, randomchoices + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/__init__.py) + +#### fake: RandomDigit + +Generate a random digit (0 to 9). + +Aliases: random_digit, randomdigit + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.RandomDigit}} + block_example: + fake: RandomDigit + +Outputs: + + Example(id=1, inline_example=7, block_example=6) + +#### fake: RandomDigitNotNull + +Generate a random non-zero digit (1 to 9). + +Aliases: random_digit_not_null, randomdigitnotnull + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.RandomDigitNotNull}} + block_example: + fake: RandomDigitNotNull + +Outputs: + + Example(id=1, inline_example=8, block_example=7) + +#### fake: RandomDigitNotNullOrEmpty + +Generate a random non-zero digit (1 to 9) or an empty string. + +This method will return an empty string 50% of the time, +and each digit has a 1/18 chance of being generated. + +:sample size=10: + +Aliases: random_digit_not_null_or_empty, randomdigitnotnullorempty + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.RandomDigitNotNullOrEmpty}} + block_example: + fake: RandomDigitNotNullOrEmpty + +Outputs: + + Example(id=1, inline_example=, block_example=2) + +#### fake: RandomDigitOrEmpty + +Generate a random digit (0 to 9) or an empty string. + +This method will return an empty string 50% of the time, +and each digit has a 1/20 chance of being generated. + +:sample size=10: + +Aliases: random_digit_or_empty, randomdigitorempty + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.RandomDigitOrEmpty}} + block_example: + fake: RandomDigitOrEmpty + +Outputs: + + Example(id=1, inline_example=8, block_example=) + +#### fake: RandomElement + +Generate a randomly sampled object from ``elements``. + +For information on the ``elements`` argument, please refer to +:meth:`random_elements() ` which +is used under the hood with the ``unique`` argument set to ``False`` and the +``length`` argument set to ``1``. + +:sample size=10: elements=OrderedDict([ +("a", 0.45), +("b", 0.35), +("c", 0.15), +("d", 0.05), +]) + +Aliases: random_element, randomelement + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/__init__.py) + +#### fake: RandomElements + +Generate a list of randomly sampled objects from ``elements``. + +Set ``unique`` to ``False`` for random sampling with replacement, and set ``unique`` to +``True`` for random sampling without replacement. + +If ``length`` is set to ``None`` or is omitted, ``length`` will be set to a random +integer from 1 to the size of ``elements``. + +The value of ``length`` cannot be greater than the number of objects +in ``elements`` if ``unique`` is set to ``True``. + +The value of ``elements`` can be any sequence type (``list``, ``tuple``, ``set``, +``string``, etc) or an ``OrderedDict`` type. If it is the latter, the keys will be +used as the objects for sampling, and the values will be used as weighted probabilities +if ``unique`` is set to ``False``. For example: + +.. code-block:: python + + # Random sampling with replacement +fake.random_elements( +elements=OrderedDict([ +("variable_1", 0.5), # Generates "variable_1" 50% of the time +("variable_2", 0.2), # Generates "variable_2" 20% of the time +("variable_3", 0.2), # Generates "variable_3" 20% of the time +("variable_4": 0.1), # Generates "variable_4" 10% of the time +]), unique=False +) + + # Random sampling without replacement (defaults to uniform distribution) +fake.random_elements( +elements=OrderedDict([ +("variable_1", 0.5), +("variable_2", 0.2), +("variable_3", 0.2), +("variable_4": 0.1), +]), unique=True +) + + + + + +("a", 0.45), +("b", 0.35), +("c", 0.15), +("d", 0.05), +]), length=20, unique=False + +("a", 0.45), +("b", 0.35), +("c", 0.15), +("d", 0.05), +]), unique=True + +Aliases: random_elements, randomelements + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/__init__.py) + +#### fake: RandomInt + +Generate a random integer between two integers ``min`` and ``max`` inclusive +while observing the provided ``step`` value. + +This method is functionally equivalent to randomly sampling an integer +from the sequence ``range(min, max + 1, step)``. + +:sample size=10: min=0, max=15 +:sample size=10: min=0, max=15, step=3 + +Aliases: random_int, randomint + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.RandomInt}} + block_example: + fake: RandomInt + +Outputs: + + Example(id=1, inline_example=9558, block_example=3578) + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.RandomInt(min=0, max=15)}} + block_example: + fake.RandomInt: + min: 0 + max: 15 + +Outputs: + + Example(id=1, inline_example=4, block_example=9) + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.RandomInt(min=0, max=15, step=3)}} + block_example: + fake.RandomInt: + min: 0 + max: 15 + step: 3 + +Outputs: + + Example(id=1, inline_example=3, block_example=0) + +#### fake: RandomLetter + +Generate a random ASCII letter (a-z and A-Z). + +Aliases: random_letter, randomletter + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.RandomLetter}} + block_example: + fake: RandomLetter + +Outputs: + + Example(id=1, inline_example=G, block_example=F) + +#### fake: RandomLetters + +Generate a list of random ASCII letters (a-z and A-Z) of the specified ``length``. + +Aliases: random_letters, randomletters + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.RandomLetters}} + block_example: + fake: RandomLetters + +Outputs: + + Example(id=1, inline_example=['P', 'x', 'e', 'q', 'A', 'W', 'f', 'C', 'K', 'C', 'Q', 'C', 'Y', 'F', 'E', 'x'], block_example=['F', 'u', 'D', 'p', 'j', 'j', 'F', 'I', 'y', 'e', 'N', 'T', 'W', 'R', 'U', 'W']) + +#### fake: RandomLowercaseLetter + +Generate a random lowercase ASCII letter (a-z). + +Aliases: random_lowercase_letter, randomlowercaseletter + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.RandomLowercaseLetter}} + block_example: + fake: RandomLowercaseLetter + +Outputs: + + Example(id=1, inline_example=q, block_example=p) + +#### fake: RandomNumber + +Generate a random integer according to the following rules: + +- If ``digits`` is ``None`` (default), its value will be set to a random +integer from 1 to 9. +- If ``fix_len`` is ``False`` (default), all integers that do not exceed +the number of ``digits`` can be generated. +- If ``fix_len`` is ``True``, only integers with the exact number of +``digits`` can be generated. + +Aliases: random_number, randomnumber + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.RandomNumber(fix_len=False)}} + block_example: + fake.RandomNumber: + fix_len: false + +Outputs: + + Example(id=1, inline_example=67013, block_example=54349339) + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.RandomNumber(fix_len=True)}} + block_example: + fake.RandomNumber: + fix_len: true + +Outputs: + + Example(id=1, inline_example=72468, block_example=711720) + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.RandomNumber(digits=3)}} + block_example: + fake.RandomNumber: + digits: 3 + +Outputs: + + Example(id=1, inline_example=913, block_example=929) + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.RandomNumber(digits=3, fix_len=False)}} + block_example: + fake.RandomNumber: + digits: 3 + fix_len: false + +Outputs: + + Example(id=1, inline_example=223, block_example=516) + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.RandomNumber(digits=3, fix_len=True)}} + block_example: + fake.RandomNumber: + digits: 3 + fix_len: true + +Outputs: + + Example(id=1, inline_example=242, block_example=388) + +#### fake: RandomSample + +Generate a list of objects randomly sampled from ``elements`` without replacement. + +For information on the ``elements`` and ``length`` arguments, please refer to +:meth:`random_elements() ` which +is used under the hood with the ``unique`` argument explicitly set to ``True``. + +Aliases: random_sample, randomsample + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/__init__.py) + +#### fake: RandomUppercaseLetter + +Generate a random uppercase ASCII letter (A-Z). + +Aliases: random_uppercase_letter, randomuppercaseletter + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.RandomUppercaseLetter}} + block_example: + fake: RandomUppercaseLetter + +Outputs: + + Example(id=1, inline_example=Q, block_example=P) + +#### fake: RandomizeNbElements + +Generate a random integer near ``number`` according to the following rules: + +- If ``le`` is ``False`` (default), allow generation up to 140% of ``number``. +If ``True``, upper bound generation is capped at 100%. +- If ``ge`` is ``False`` (default), allow generation down to 60% of ``number``. +If ``True``, lower bound generation is capped at 100%. +- If a numerical value for ``min`` is provided, generated values less than ``min`` +will be clamped at ``min``. +- If a numerical value for ``max`` is provided, generated values greater than +``max`` will be clamped at ``max``. +- If both ``le`` and ``ge`` are ``True``, the value of ``number`` will automatically +be returned, regardless of the values supplied for ``min`` and ``max``. + +Aliases: randomize_nb_elements, randomizenbelements + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.RandomizeNbElements(number=100)}} + block_example: + fake.RandomizeNbElements: + number: 100 + +Outputs: + + Example(id=1, inline_example=109, block_example=113) + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.RandomizeNbElements(number=100, ge=True)}} + block_example: + fake.RandomizeNbElements: + number: 100 + ge: true + +Outputs: + + Example(id=1, inline_example=102, block_example=116) + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.RandomizeNbElements(number=100, ge=True, min=120)}} + block_example: + fake.RandomizeNbElements: + number: 100 + ge: true + min: 120 + +Outputs: + + Example(id=1, inline_example=132, block_example=131) + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.RandomizeNbElements(number=100, le=True)}} + block_example: + fake.RandomizeNbElements: + number: 100 + le: true + +Outputs: + + Example(id=1, inline_example=85, block_example=79) + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.RandomizeNbElements(number=100, le=True, max=80)}} + block_example: + fake.RandomizeNbElements: + number: 100 + le: true + max: 80 + +Outputs: + + Example(id=1, inline_example=80, block_example=80) + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.RandomizeNbElements(number=79, le=True, ge=True, min=80)}} + block_example: + fake.RandomizeNbElements: + number: 79 + le: true + ge: true + min: 80 + +Outputs: + + Example(id=1, inline_example=79, block_example=79) + +### Python Fakers + +#### fake: Pybool + +Aliases: pybool + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/python/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.Pybool}} + block_example: + fake: Pybool + +Outputs: + + Example(id=1, inline_example=True, block_example=True) + +#### fake: Pydecimal + +Aliases: pydecimal + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/python/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.Pydecimal}} + block_example: + fake: Pydecimal + +Outputs: + + Example(id=1, inline_example=333018422.10356, block_example=935868384284.7) + +#### fake: Pydict + +Returns a dictionary. + +:nb_elements: number of elements for dictionary +:variable_nb_elements: is use variable number of elements for dictionary +:value_types: type of dictionary values + +Aliases: pydict + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/python/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.Pydict}} + block_example: + fake: Pydict + +Outputs: + + Example(id=1, inline_example={'however': 7230, 'issue': 'tXejffFiKWjvjXrBsGeN', 'across': -9.1092906014666, 'key': 'pNGCiKyJNmNoZgTcnBEu', 'should': 'MsTIkednBgSUNdSogBkf', 'wear': 'todd75@hotmail.com'}, block_example={'certainly': 'elarson@yahoo.com', 'close': datetime.datetime(1991, 8, 28, 21, 39, 37), 'candidate': Decimal('40561592774.2339'), 'same': Decimal('0.66363066127717'), 'camera': 165, 'I': datetime.datetime(1974, 7, 10, 19, 2, 25), 'institution': 'xdavis@gibson.com', 'perhaps': -19796477880609.9, 'management': 7110.96468809015, 'chair': 6293, 'opportunity': 'rHJhWhqkjsZwzLPwkKVb', 'relate': 'bridgetrivera@rich.com', 'firm': 'http://sherman-hartman.com/about.asp', 'health': 'qbrock@hotmail.com'}) + +#### fake: Pyfloat + +Aliases: pyfloat + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/python/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.Pyfloat}} + block_example: + fake: Pyfloat + +Outputs: + + Example(id=1, inline_example=333018422.10356, block_example=935868384284.7) + +#### fake: Pyint + +Aliases: pyint + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/python/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.Pyint}} + block_example: + fake: Pyint + +Outputs: + + Example(id=1, inline_example=7961, block_example=6634) + +#### fake: Pyiterable + +Aliases: pyiterable + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/python/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.Pyiterable}} + block_example: + fake: Pyiterable + +Outputs: + + Example(id=1, inline_example=['tyronecervantes@schultz.info', -57431325491810.6, 1020, 'HgoRcbvzSLJhZvFucyhb', 'https://www.houston.com/category/', Decimal('78.8219282425171')], block_example={'jfrXgYsypWXHjZfEiUXP', Decimal('46809.968437303'), 'vLqkpyXPoDJPxuNwmxWh', 'mjtISFuKgpvWEpsmGHBt', 8328, 'zUXIDleQUOKvpfwDVWvf', 'cherylmcmahon@yahoo.com', 2036, Decimal('39529332399.3'), 'NGCiKyJNmNoZgTcnBEuf', Decimal('-33400472.39132'), 'brycewalls@strickland-blair.com', 'caldwellcaitlyn@lewis.com', 'MbxJbVYLedsbsaYQdUkk'}) + +#### fake: Pylist + +Aliases: pylist + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/python/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.Pylist}} + block_example: + fake: Pylist + +Outputs: + + Example(id=1, inline_example=[1376, 'vfOMbxJbVYLedsbsaYQd', 'kkJWgatbFSjfrXgYsypW', datetime.datetime(2013, 4, 10, 18, 29, 48), 3015, 'http://quinn.com/', 'qmNpvcgbedvCMhvHextX', 'taYUwtXejffFiKWjvjXr', datetime.datetime(1979, 9, 14, 12, 49, 15), 7576, 'nfrost@johnson-benton.info', 'http://www.chavez-galvan.com/tags/tag/posts/home/', 'mariahhebert@yahoo.com'], block_example=['wongwhitney@smith.biz', datetime.datetime(2009, 7, 31, 3, 33, 54), 7284, 'MsTIkednBgSUNdSogBkf', 'todd75@hotmail.com', 'geraldorr@doyle.org', Decimal('-362.522405940924'), 3571, Decimal('-66131725.1010359')]) + +#### fake: Pyset + +Aliases: pyset + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/python/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.Pyset}} + block_example: + fake: Pyset + +Outputs: + + Example(id=1, inline_example={1376, 'nfrost@johnson-benton.info', 'taYUwtXejffFiKWjvjXr', 3015, 'mariahhebert@yahoo.com', datetime.datetime(1979, 9, 14, 12, 49, 15), datetime.datetime(2013, 4, 10, 18, 29, 48), 'kkJWgatbFSjfrXgYsypW', 'vfOMbxJbVYLedsbsaYQd', 'qmNpvcgbedvCMhvHextX', 'http://www.chavez-galvan.com/tags/tag/posts/home/', 7576, 'http://quinn.com/'}, block_example={'geraldorr@doyle.org', Decimal('-362.522405940924'), 'wongwhitney@smith.biz', 'todd75@hotmail.com', 3571, 7284, Decimal('-66131725.1010359'), datetime.datetime(2009, 7, 31, 3, 33, 54), 'MsTIkednBgSUNdSogBkf'}) + +#### fake: Pystr + +Generates a random string of upper and lowercase letters. +:type min_chars: int +:type max_chars: int +:return: String. Random of random length between min and max characters. + +Aliases: pystr + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/python/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.Pystr}} + block_example: + fake: Pystr + +Outputs: + + Example(id=1, inline_example=GRmMglPrQfhKcDVBJbHF, block_example=DutYbbXjgkPWbwfnlHsj) + +#### fake: PystrFormat + +Aliases: pystr_format, pystrformat + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/python/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.PystrFormat}} + block_example: + fake: PystrFormat + +Outputs: + + Example(id=1, inline_example=C9-3877113u, block_example=U0-8018541q) + +#### fake: Pystruct + +Aliases: pystruct + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/python/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.Pystruct}} + block_example: + fake: Pystruct + +Outputs: + + Example(id=1, inline_example=(['AlnRDYPnKrQpTzKvYjZJ', 'ANuZspJKtvkFnBczSvFj', 'GaNPwqXmgqcYwhAuFFQU', 'AwPyLGMUlJalMplCUClp', 'HoHCECnIeqpwakSPaFAf', 'rfzpPsEjOgoRESSZZKyZ', 2775, Decimal('-624.560558663604'), 'ABtOefKYYukvkNLyvsML', 'efFduoNGEJBMQJHIrnoI'], {'more': 'PnYFlpEauZmcjxERRLrI', 'mean': -3380.60709450259, 'raise': 'IPUlkGTQQinWLLRJpTrX', 'woman': 'raymondjacobs@marks.com', 'per': 'qsingleton@hotmail.com', 'direction': 'dwiley@palmer-hays.info', 'medical': 'jimmy52@gmail.com', 'seem': 9318, 'opportunity': Decimal('7816622550.5122'), 'win': Decimal('-3055399609094.3')}, {'likely': {0: 'otXBHKVvOxrMFqEfVbdK', 1: ['WvWAepzTdCCTtyIlHxmm', 'http://singh.biz/homepage/', 'ExvmtRxZXngKbkpmxXzq'], 2: {0: 'pfksTjPmkHNctpoGaWXg', 1: datetime.datetime(1970, 1, 20, 18, 9, 53), 2: [datetime.datetime(2019, 3, 20, 4, 21, 19), 'EGoIizbIEqCmLUsPRhoy']}}, 'successful': {1: 'FUdbrbputMNKRmTxTqxZ', 2: ['QfOxRhpBHrJWrdsahIog', 'irASNEYAkztuzQCKWgLP', 'https://www.spears.com/register.asp'], 3: {1: 'djMgmkbszXrreHUJzGqs', 2: 1542, 3: ['JhDPmefptRyNmKYvScec', 'http://cantu.org/author/']}}, 'can': {2: 'melinda30@gmail.com', 3: [-2971150070.28733, 'HVGSTXNXIMWXYaEXHjir', datetime.datetime(1997, 10, 15, 7, 21, 19)], 4: {2: 'teHuAcZpKPitsiINHMev', 3: Decimal('-3903478892.99996'), 4: ['LXezkrcAngrgTKMZWpFz', 7.17977529165436]}}, 'identify': {3: 'dWgdfLgtXFbfFFDPiDnp', 4: ['http://graham-schmidt.com/main/main/tags/post.htm', 'nxUWoJCUpxEvvkMQHDTS', 'AdLsLrfTUwpuFoEGaiqF'], 5: {3: datetime.datetime(2001, 10, 23, 21, 7, 8), 4: 3321, 5: [994, 8248]}}, 'wrong': {4: 6262, 5: [9966, 3444, 131], 6: {4: 'fAHHfrlrKtqerPRHHTvu', 5: 'http://brennan-dudley.com/', 6: [-48.262033391978, 5463]}}, 'change': {5: 'tVTRrnfOuyedRDijsnha', 6: [7279, -88913121756.539, 'IapbxSUIRyeyLlgZxHZK'], 7: {5: 8851, 6: -60544431.5256728, 7: ['http://www.ferrell.com/terms.php', Decimal('-82.3137650741875')]}}, 'present': {6: 'txXhOTfqojIVkyCoOuft', 7: [datetime.datetime(1995, 12, 29, 0, 20, 55), 58853.2993449084, 32008793.30265], 8: {6: 'bwpcQfqQMwNnvQqPwKjx', 7: 'fjnOoffkdJBcFzUiJkFX', 8: ['VaTLcWeksUwSmKWCVxkR', datetime.datetime(2012, 1, 18, 15, 54, 31)]}}, 'lay': {7: 'natashaherring@watts.com', 8: ['https://hodges.biz/tags/categories/main/', Decimal('87.9261994045045'), 'qOVqzLNoDTdRKRUMIeDb'], 9: {7: 4196, 8: 'AXagmwKEFSdOlOWTBSAT', 9: [Decimal('-1073655449.14833'), 54071212.3645809]}}, 'benefit': {8: -263600384742.957, 9: ['KvGhYNQkRqrITJpQhXKD', 'tWlgjJBZhbcgRSJtyOBg', Decimal('-7.7640121431953')], 10: {8: Decimal('709.678338409695'), 9: 7476, 10: [993, 'kIMaXOkrryujudzakkqA']}}, 'front': {9: 'uaDZZmMjQFQJRhojglex', 10: [145, 'kKcaSVbnsEGYoutRkVIz', 'coUYiMyXVmWbhNoVvYFn'], 11: {9: 1787, 10: 'https://odom.net/main.htm', 11: ['AqBknmSuStqIvQHKYRrx', 'UCCelgqaAasfmInaQCTn']}}}), block_example=(['OXXtemWVJOLAoRkQGPSm', Decimal('28758635.2898326'), 2342, 4044, 'https://graves.org/tag/post/', 1771, 'QuuFCvjVCVBgORMsHOzL', 'NWrGYdSxVtcAWCmJCCml', 'anBHZZLtTIJqQsrEdbwv', 'https://www.hamilton.com/'], {'blue': 'WOFXuxIRpgblNdeqrKwf', 'modern': 'gmueller@gmail.com', 'teacher': 8893, 'account': 3187, 'finally': Decimal('-18247154934.426'), 'same': 6671, 'throw': 6331, 'public': 29116.8304143767, 'single': 'https://ritter-mccoy.com/register.html', 'discussion': 'WMxPLafnTuVegvMMkqgP'}, {'order': {0: 'http://ryan.com/login.jsp', 1: ['https://www.mccall-vasquez.org/posts/categories/search.jsp', 'ksMvjXWSzZdIbrDzwWTU', 'kItUrFRrgsosYSERAWnU'], 2: {0: 'http://www.jenkins-parks.com/', 1: -7529800541539.8, 2: ['CCjKyDWZFAYbiKqzGuEq', 'nKEYyQEsFUlHvhBFButr']}}, 'student': {1: 'YRGgRAEClCyUWZBpeboc', 2: [73334959.7930117, Decimal('-6339158106.71388'), 309050839.29914], 3: {1: 'lHHZBjvmeNaqyhUsNZpt', 2: 'usparks@hotmail.com', 3: ['http://melton-medina.org/category/', 5464]}}, 'executive': {2: Decimal('-49.438926121434'), 3: [datetime.datetime(1999, 11, 21, 5, 44, 5), 'pIaVGadFmrTOATEoYddU', datetime.datetime(1992, 9, 22, 15, 17, 11)], 4: {2: 'PMXrGVmaCwuuJBwJszrB', 3: 1657, 4: [datetime.datetime(2012, 6, 28, 13, 51, 49), 'jWQvXcFsPZpGHqpfXzKO']}}, 'kind': {3: 'http://www.haley-maldonado.com/categories/privacy.php', 4: ['http://bradley-meza.net/search/tags/search/faq/', 'https://www.archer-carpenter.com/posts/tag/list/privacy.php', datetime.datetime(1985, 7, 10, 19, 37, 21)], 5: {3: datetime.datetime(2020, 12, 3, 3, 58, 20), 4: 'YNTymfhoOgZcDDAiySnt', 5: [-86165295881087.6, datetime.datetime(1974, 5, 25, 6, 34, 53)]}}, 'quality': {4: 'http://www.sanders-floyd.com/main/category/login/', 5: [Decimal('5158295364.1217'), 'claysydney@yahoo.com', 1619], 6: {4: 'wallcathy@hinton.org', 5: 9137.47670418247, 6: [datetime.datetime(1984, 4, 3, 2, 1, 37), 'IMBQiNbnexoTcNTGkaeR']}}, 'allow': {5: 'HqGjPKBFwAArotfaNTrp', 6: ['UcjfsRbrWDqTNcTVzGvr', 'heidigutierrez@zimmerman.com', 'xUFsPmEXaEOCmTFvwTJZ'], 7: {5: 'drakesummer@martin.com', 6: Decimal('444.876804221886'), 7: ['jesusrandall@gonzalez.com', 'BauHMCILyGKBobSKTzkk']}}, 'strategy': {6: 'https://hess-hess.com/tag/main/', 7: ['qTwogmFkYTzXcIycKGJl', 'ChDHNOhInFURxoJlKkRc', 'TElVPSMBKzClsvCwVOOo'], 8: {6: -40890567296284.0, 7: 'sgRsEOKCiaERZhVVpyLl', 8: ['BPFYrPDkgzkucwtyQHrb', 'xYMJXbhlNScBWUZIslCE']}}, 'wide': {7: 'gWciUUeILqBHxDmntujX', 8: [-29858635883003.3, 'yeuUzLxzoJkVRnAXSfvt', 'OHnnxvKvUfhNTBCEQRqu'], 9: {7: datetime.datetime(2018, 7, 19, 3, 56, 29), 8: -0.1825490280262, 9: ['tdRlEWsCvfWThwaXErak', 'http://pope.info/search/homepage.jsp']}}, 'your': {8: 2326.8009205109, 9: ['SfBMDlzvgsZchSSfSSzj', Decimal('4.96204389699817'), 'http://foley.com/author/'], 10: {8: 8555, 9: 'barrross@yahoo.com', 10: ['EZJsaXKRmRpJDwnNKDkX', 'hxCMgjRxjMSiaLwRcDSz']}}, 'test': {9: Decimal('652198.966221436'), 10: ['KJQeIvLHqDNVUjvWFemp', 4734, 812], 11: {9: 'rmanning@mcmahon.com', 10: 'fbcYXXDheRDYkmOdIlIP', 11: [Decimal('-47753760363090.5'), 'yharmon@owen.com']}}})) + +#### fake: Pytuple + +Aliases: pytuple + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/python/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.Pytuple}} + block_example: + fake: Pytuple + +Outputs: + + Example(id=1, inline_example=(1376, 'vfOMbxJbVYLedsbsaYQd', 'kkJWgatbFSjfrXgYsypW', datetime.datetime(2013, 4, 10, 18, 29, 48), 3015, 'http://quinn.com/', 'qmNpvcgbedvCMhvHextX', 'taYUwtXejffFiKWjvjXr', datetime.datetime(1979, 9, 14, 12, 49, 15), 7576, 'nfrost@johnson-benton.info', 'http://www.chavez-galvan.com/tags/tag/posts/home/', 'mariahhebert@yahoo.com'), block_example=('wongwhitney@smith.biz', datetime.datetime(2009, 7, 31, 3, 33, 54), 7284, 'MsTIkednBgSUNdSogBkf', 'todd75@hotmail.com', 'geraldorr@doyle.org', Decimal('-362.522405940924'), 3571, Decimal('-66131725.1010359'))) + +### Ssn Fakers + +#### fake: Ein + +Generate a random United States Employer Identification Number (EIN). + +An United States An Employer Identification Number (EIN) is +also known as a Federal Tax Identification Number, and is +used to identify a business entity. EINs follow a format of a +two-digit prefix followed by a hyphen and a seven-digit sequence: + ##-###### + +https://www.irs.gov/businesses/small-businesses-self-employed/employer-id-numbers + +Aliases: ein + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/ssn/en_US/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.Ein}} + block_example: + fake: Ein + +Outputs: + + Example(id=1, inline_example=88-3664860, block_example=76-2336625) + +#### fake: InvalidSsn + +Generate a random invalid United States Social Security Identification Number (SSN). + +Invalid SSNs have the following characteristics: +Cannot begin with the number 9 +Cannot begin with 666 in positions 1 - 3 +Cannot begin with 000 in positions 1 - 3 +Cannot contain 00 in positions 4 - 5 +Cannot contain 0000 in positions 6 - 9 + +https://www.ssa.gov/kc/SSAFactSheet--IssuingSSNs.pdf + +Additionally, return an invalid SSN that is NOT a valid ITIN by excluding certain ITIN related "group" values + +Aliases: invalid_ssn, invalidssn + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/ssn/en_US/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.InvalidSsn}} + block_example: + fake: InvalidSsn + +Outputs: + + Example(id=1, inline_example=516-00-4617, block_example=143-12-0000) + +#### fake: Itin + +Generate a random United States Individual Taxpayer Identification Number (ITIN). + +An United States Individual Taxpayer Identification Number +(ITIN) is a tax processing number issued by the Internal +Revenue Service. It is a nine-digit number that always begins +with the number 9 and has a range of 70-88 in the fourth and +fifth digit. Effective April 12, 2011, the range was extended +to include 900-70-0000 through 999-88-9999, 900-90-0000 +through 999-92-9999 and 900-94-0000 through 999-99-9999. +https://www.irs.gov/individuals/international-taxpayers/general-itin-information + +Aliases: itin + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/ssn/en_US/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.Itin}} + block_example: + fake: Itin + +Outputs: + + Example(id=1, inline_example=917-90-1553, block_example=932-94-8725) + +#### fake: Ssn + +Generate a random United States Taxpayer Identification Number of the specified type. + +If no type is specified, a US SSN is returned. + +Aliases: ssn + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/ssn/en_US/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.Ssn}} + block_example: + fake: Ssn + +Outputs: + + Example(id=1, inline_example=289-18-1554, block_example=634-33-8726) + +### User_Agent Fakers + +#### fake: AndroidPlatformToken + +Generate an Android platform token used in user agent strings. + +Aliases: android_platform_token, androidplatformtoken + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/user_agent/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.AndroidPlatformToken}} + block_example: + fake: AndroidPlatformToken + +Outputs: + + Example(id=1, inline_example=Android 1.5, block_example=Android 2.3.5) + +#### fake: Chrome + +Generate a Chrome web browser user agent string. + +Aliases: chrome + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/user_agent/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.Chrome}} + block_example: + fake: Chrome + +Outputs: + + Example(id=1, inline_example=Mozilla/5.0 (X11; Linux i686) AppleWebKit/531.2 (KHTML, like Gecko) Chrome/63.0.818.0 Safari/531.2, block_example=Mozilla/5.0 (Linux; Android 4.4) AppleWebKit/535.0 (KHTML, like Gecko) Chrome/32.0.844.0 Safari/535.0) + +#### fake: Firefox + +Generate a Mozilla Firefox web browser user agent string. + +Aliases: firefox + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/user_agent/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.Firefox}} + block_example: + fake: Firefox + +Outputs: + + Example(id=1, inline_example=Mozilla/5.0 (X11; Linux x86_64; rv:1.9.7.20) Gecko/2016-10-28 01:20:46 Firefox/12.0, block_example=Mozilla/5.0 (Macintosh; PPC Mac OS X 10 12_8; rv:1.9.5.20) Gecko/2010-01-10 11:18:29 Firefox/3.8) + +#### fake: InternetExplorer + +Generate an IE web browser user agent string. + +Aliases: internet_explorer, internetexplorer + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/user_agent/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.InternetExplorer}} + block_example: + fake: InternetExplorer + +Outputs: + + Example(id=1, inline_example=Mozilla/5.0 (compatible; MSIE 7.0; Windows 98; Trident/5.0), block_example=Mozilla/5.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/5.0)) + +#### fake: IosPlatformToken + +Generate an iOS platform token used in user agent strings. + +Aliases: ios_platform_token, iosplatformtoken + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/user_agent/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.IosPlatformToken}} + block_example: + fake: IosPlatformToken + +Outputs: + + Example(id=1, inline_example=iPhone; CPU iPhone OS 10_3_4 like Mac OS X, block_example=iPhone; CPU iPhone OS 7_1_2 like Mac OS X) + +#### fake: LinuxPlatformToken + +Generate a Linux platform token used in user agent strings. + +Aliases: linux_platform_token, linuxplatformtoken + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/user_agent/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.LinuxPlatformToken}} + block_example: + fake: LinuxPlatformToken + +Outputs: + + Example(id=1, inline_example=X11; Linux x86_64, block_example=X11; Linux x86_64) + +#### fake: LinuxProcessor + +Generate a Linux processor token used in user agent strings. + +Aliases: linux_processor, linuxprocessor + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/user_agent/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.LinuxProcessor}} + block_example: + fake: LinuxProcessor + +Outputs: + + Example(id=1, inline_example=x86_64, block_example=x86_64) + +#### fake: MacPlatformToken + +Generate a MacOS platform token used in user agent strings. + +Aliases: mac_platform_token, macplatformtoken + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/user_agent/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.MacPlatformToken}} + block_example: + fake: MacPlatformToken + +Outputs: + + Example(id=1, inline_example=Macintosh; U; Intel Mac OS X 10 7_4, block_example=Macintosh; Intel Mac OS X 10 6_5) + +#### fake: MacProcessor + +Generate a MacOS processor token used in user agent strings. + +Aliases: mac_processor, macprocessor + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/user_agent/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.MacProcessor}} + block_example: + fake: MacProcessor + +Outputs: + + Example(id=1, inline_example=U; PPC, block_example=U; Intel) + +#### fake: Opera + +Generate an Opera web browser user agent string. + +Aliases: opera + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/user_agent/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.Opera}} + block_example: + fake: Opera + +Outputs: + + Example(id=1, inline_example=Opera/9.95.(X11; Linux x86_64; bhb-IN) Presto/2.9.162 Version/12.00, block_example=Opera/8.51.(X11; Linux i686; the-NP) Presto/2.9.186 Version/11.00) + +#### fake: Safari + +Generate a Safari web browser user agent string. + +Aliases: safari + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/user_agent/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.Safari}} + block_example: + fake: Safari + +Outputs: + + Example(id=1, inline_example=Mozilla/5.0 (Windows; U; Windows NT 6.1) AppleWebKit/535.16.7 (KHTML, like Gecko) Version/5.1 Safari/535.16.7, block_example=Mozilla/5.0 (iPod; U; CPU iPhone OS 3_0 like Mac OS X; fa-IR) AppleWebKit/531.47.3 (KHTML, like Gecko) Version/3.0.5 Mobile/8B112 Safari/6531.47.3) + +#### fake: UserAgent + +Generate a random web browser user agent string. + +Aliases: user_agent, useragent + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/user_agent/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.UserAgent}} + block_example: + fake: UserAgent + +Outputs: + + Example(id=1, inline_example=Mozilla/5.0 (Windows NT 5.0; the-NP; rv:1.9.1.20) Gecko/2016-08-28 10:17:44 Firefox/3.8, block_example=Mozilla/5.0 (Macintosh; Intel Mac OS X 10 5_8; rv:1.9.5.20) Gecko/2020-03-30 18:10:19 Firefox/3.8) + +#### fake: WindowsPlatformToken + +Generate a Windows platform token used in user agent strings. + +Aliases: windows_platform_token, windowsplatformtoken + +Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/user_agent/__init__.py) + +##### Samples + +Recipe: + + - var: snowfakery_locale + value: en_US + - object: Example + fields: + inline_example: ${{fake.WindowsPlatformToken}} + block_example: + fake: WindowsPlatformToken + +Outputs: + + Example(id=1, inline_example=Windows NT 5.2, block_example=Windows NT 5.1) + diff --git a/mkdocs.yml b/mkdocs.yml index caebea71..d065843c 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -14,4 +14,6 @@ markdown_extensions: toc_depth: 4 plugins: - search - - snowfakery_fakes # this causes a timeout on ReadTheDocs.org + - snowfakery_fakes: + # build_locales: True # do or do not generate locales + # should be True on the fake-data-docs branch diff --git a/snowfakery/tools/mkdocs.py b/snowfakery/tools/mkdocs.py index 2bd058c2..fd7edea2 100644 --- a/snowfakery/tools/mkdocs.py +++ b/snowfakery/tools/mkdocs.py @@ -4,16 +4,20 @@ from unittest.mock import patch from mkdocs.plugins import BasePlugin +import mkdocs class Plugin(BasePlugin): + config_scheme = ( + ("build_locales", mkdocs.config.config_options.Type(bool, default=False)), + ) + def on_config(self, config): """Look for and load main_mkdocs_plugin in tools/faker_docs_utils/mkdocs_plugins.py This bootstrap plugin is needed because that other one is never "installed" It is just present in the repo. So it can't have an official entry point in setup.py. """ - print(config) docs_dir = config["docs_dir"] plugins_dir = Path(docs_dir).parent / "tools/faker_docs_utils/mkdocs_plugins" new_sys_path = [*sys.path, str(plugins_dir)] @@ -21,4 +25,5 @@ def on_config(self, config): module = import_module("main_mkdocs_plugin") main_plugin = module.Plugin() config["plugins"]["main_mkdocs_plugin"] = main_plugin + main_plugin.config = self.config main_plugin.on_config(config) diff --git a/tools/faker_docs_utils/faker_markdown.py b/tools/faker_docs_utils/faker_markdown.py index 1c061590..38266b85 100644 --- a/tools/faker_docs_utils/faker_markdown.py +++ b/tools/faker_docs_utils/faker_markdown.py @@ -35,7 +35,7 @@ def country_for_locale(locale: str): return f.current_country() -def other_locales(current_locale: str): +def locales_as_markdown(current_locale: str): def format_link(locale: str): try: country_name = country_for_locale(locale) @@ -59,20 +59,25 @@ def output(*args, **kwargs): print(*args, **kwargs, file=outfile) output(f"# Fake Data: {locale}\n") + output( - f"Current Locale: {locale} ({faker.current_country()}) [[Other Locales](#other-locales)]" + f"""The basic concepts of fake data are described in +the [main docs](index.md#fake-data). + +Current Locale: {locale} ({faker.current_country()})\n + +Our fake data can be localized to many languages. We have +[detailed docs](https://snowfakery.readthedocs.io/en/feature-fake-data-docs/locales.html) +about the other languages. +""" ) - output() + output("[TOC]\n") output("## Commonly Used\n") summarize_categories(output, [f for f in all_fakers if f.common], "", locale) output("## Rarely Used\n") summarize_categories(output, [f for f in all_fakers if not f.common], "", locale) - locales = other_locales(locale) - if locales: - output("## Other Locales\n") - output(locales) def summarize_categories(output, fakers, common: str, locale): @@ -132,3 +137,15 @@ def generate_markdown_for_all_locales(path: Path, locales=AVAILABLE_LOCALES): for locale in locales: with Path(path, f"{locale}.md").open("w") as f: generate_markdown_for_fakers(f, locale) + + +def generate_locales_index(path: Path): + with Path(path).open("w") as outfile: + + def output(*args, **kwargs): + print(*args, **kwargs, file=outfile) + + locales = locales_as_markdown(None) + if locales: + output("## Faker Locales\n") + output(locales) diff --git a/tools/faker_docs_utils/mkdocs_plugins/main_mkdocs_plugin.py b/tools/faker_docs_utils/mkdocs_plugins/main_mkdocs_plugin.py index cc383f1d..9888803d 100644 --- a/tools/faker_docs_utils/mkdocs_plugins/main_mkdocs_plugin.py +++ b/tools/faker_docs_utils/mkdocs_plugins/main_mkdocs_plugin.py @@ -33,6 +33,14 @@ def on_pre_build(self, config): ): from tools.faker_docs_utils.faker_markdown import ( generate_markdown_for_all_locales, + generate_markdown_for_fakers, + generate_locales_index, ) - generate_markdown_for_all_locales(faker_docs_dir) + fakerdocs_md = root_dir / "docs/fakedata.md" + with fakerdocs_md.open("w") as f: + generate_markdown_for_fakers(f, "en_US") + + if self.config.get("build_locales"): + generate_markdown_for_all_locales(faker_docs_dir) + generate_locales_index("docs/locales.md") From 1b0669ad84bd480cb28d1d2d163350fa222cb4c8 Mon Sep 17 00:00:00 2001 From: Paul Prescod Date: Sun, 13 Jun 2021 14:08:27 -0700 Subject: [PATCH 06/53] Enable locale building --- mkdocs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mkdocs.yml b/mkdocs.yml index d065843c..9a3e169e 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -15,5 +15,5 @@ markdown_extensions: plugins: - search - snowfakery_fakes: - # build_locales: True # do or do not generate locales + build_locales: True # do or do not generate locales # should be True on the fake-data-docs branch From 623dabdfed6b8ec14f73e96d293cb955aae3dd4c Mon Sep 17 00:00:00 2001 From: Paul Prescod Date: Sun, 13 Jun 2021 14:15:39 -0700 Subject: [PATCH 07/53] Improve nav title --- mkdocs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mkdocs.yml b/mkdocs.yml index 9a3e169e..da26450b 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -5,7 +5,7 @@ repo_url: https://github.com/SFDO-Tooling/Snowfakery/ nav: - index.md - salesforce.md - - fakedata.md + - Fake Data: fakedata.md - embedding.md - extending.md markdown_extensions: From bcd449c2aeddccbf5e6fd1b19eebf6c616897661 Mon Sep 17 00:00:00 2001 From: Paul Prescod Date: Sun, 13 Jun 2021 14:19:38 -0700 Subject: [PATCH 08/53] Fix link --- tools/faker_docs_utils/faker_markdown.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tools/faker_docs_utils/faker_markdown.py b/tools/faker_docs_utils/faker_markdown.py index 38266b85..b5ce548e 100644 --- a/tools/faker_docs_utils/faker_markdown.py +++ b/tools/faker_docs_utils/faker_markdown.py @@ -42,7 +42,7 @@ def format_link(locale: str): except (ValueError, AttributeError): return None link_text = f"{locale} : {country_name}" - return f" - [{link_text}]({locale}.md)\n" + return f" - [{link_text}](fakedata/{locale}.md)\n" other_locales = [locale for locale in AVAILABLE_LOCALES if locale != current_locale] links = [format_link(locale) for locale in other_locales] @@ -64,11 +64,12 @@ def output(*args, **kwargs): f"""The basic concepts of fake data are described in the [main docs](index.md#fake-data). -Current Locale: {locale} ({faker.current_country()})\n - Our fake data can be localized to many languages. We have [detailed docs](https://snowfakery.readthedocs.io/en/feature-fake-data-docs/locales.html) about the other languages. + +Current Locale: {locale} ({faker.current_country()})\n + """ ) From 04f110ec28b0ec3cfd4db811e30e485081995991 Mon Sep 17 00:00:00 2001 From: Paul Prescod Date: Sun, 13 Jun 2021 15:08:44 -0700 Subject: [PATCH 09/53] Doc reorg --- docs/index.md | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/docs/index.md b/docs/index.md index 8c9e9248..903fac41 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1434,7 +1434,7 @@ other databases so we can have a sense of what works well and what does not. -## Plugins and Providers +### Plugins and Providers Plugins and Providers allow Snowfakery to be extended with Python code. A plugin adds new functions to Snowfakery. A Provider adds new capabilities to the Faker library which is exposed to Snowfakery users through the fake: keyword. @@ -1444,9 +1444,9 @@ You include either Plugins or Providers in a Snowfakery file like this: - plugin: package.module.classname ``` -## Built-in Plugins +### Built-in Plugins -### Advanced Math +#### Advanced Math Snowfakery has a "Math" plugin which gives you access to all features from Python's [`math`](https://docs.python.org/3/library/math.html) module plus @@ -1701,7 +1701,9 @@ There are several examples [in the Snowfakery repository](https://github.com/SFD Salesforce-specific patterns and tools are described in [Using Snowfakery with Salesforce](salesforce.md) -## Snowfakery Glossary +## Appendices + +### Snowfakery Glossary - Object: When we think about our Rows in the context of each other, we often use the word “Object”. That’s because rows often *represent* real-world entities like houses (or at least their, addresses), organizations and people (in this case its acceptable to objectify people). See also: “Rows” - Object Template: These represent instructions on how to create a row, or multiple rows in a database. Each row represents a real-world Object. @@ -1711,7 +1713,7 @@ Salesforce-specific patterns and tools are described in - Singleton: A singleton is an Object Template that generates a single row regardless of how many times the recipe is iterated over. - YAML: YAML is a relatively simple, human-readable format. You can learn more about it at [yaml.org](http://yaml.org/). But you can also just pick up the basics of it by reading along. -## Security Profile of Snowfakery +### Appendix: Security Profile of Snowfakery Snowfakery should be considered a domain-specific programming language with access to most of the power of Python. It can load Python plugins and @@ -1720,7 +1722,7 @@ environment that has access to secure resources such as passwords, network connections, etc. -## Appendix: The Age Old Puzzle +### Appendix: The Age Old Puzzle ```yaml # As I was going to St. Ives, From c6d7b68d7186e0f893aed05e309f37bdaa47505f Mon Sep 17 00:00:00 2001 From: Paul Prescod Date: Sun, 13 Jun 2021 15:28:07 -0700 Subject: [PATCH 10/53] favicon --- custom_theme/img/favicon.ico | Bin 0 -> 15406 bytes mkdocs.yml | 1 + 2 files changed, 1 insertion(+) create mode 100755 custom_theme/img/favicon.ico diff --git a/custom_theme/img/favicon.ico b/custom_theme/img/favicon.ico new file mode 100755 index 0000000000000000000000000000000000000000..4ef032f96d6d1e7aaa7246a74e82457b49838bad GIT binary patch literal 15406 zcmeHOeT-CB6(3sq6+cRA(NrOzHI-`BR-kEZs$i(L`0-DJ@gJM2v7$*^tBpiT=@@qB zy~hG7N?T&0T_Ta9ERB>_)PxA#nfGR9*McR{Ko=;q)mjQ&*qJvo3(w#0zISHtJl>lR znB9fONp9|a_nxnN@44rmd+wb?VnX7=#H2|H zyu5k2n=w`q#@n8pSaQsbu4BB+#4_vHhVNB`Wm$ejXW0im&zn%PjRW5P*@o`}ge8vPqmO?DkIhKEuHAXN)VogV2Tav(v;jX|vdzsdaHQUQF?n&>F@6Dj z4{e*g=dE|KO~+>)+Xw@GtBIpva>hKrk48^9Ykn8>9|g=ljM+V|oqC9gW!6=)=F$MB zM~w||y=3wNZ{vasMHc3TY{yjaSdTQw1l;wWZB5Z(h@)^Z7GZqC5=Y_M#_?Eu;JP9C zDI;ao0T0erz zd~kcj`VH!IxOS9jXQm^~L85&cjUUEv8`Ege4%6KG?0uKGIrC1;`32I3IX}!K-)tic zVWqBJc`;*t8-4Z4IkS6Xu&#CftYaHt2-_~cLdX02PbXo0_K`mLuA^-b{y}-2Y6A>m z1@BDqL+MqQ!Dc_=ri~Bl_;00?SL!lg4Zg-id4xA%bR0Lo{2Jga75lHZ#g)sBHH-AH zZXXZBkUs26-X8~!g`Zd#=1pAE@M&4I!nESPU)-3y7&6m7?~8(|9S60y^hNO|E@{wS z%f1ptk9BUwyc2f#)6$MH#U5#Tu;U++Iz3n8khPAMk>Yq0mo$)`5!^~9bu0F+`SL9} zVBRP>)+yvq6*I83L#0qJMgwUM4PSz_vbE?CqFVvaJpHK85->Jeno# z$G(r~mRTre6)g5`;}05GO|cPw;*vkoQ{Xuil=Fr3$T;f+X+O$N>RW(=PWyU={D|jm ztl7r}ryhUe5Lf7MonWrMq1!K^Be~a~nv5~{S_OWU;01Z_P}Z0&aFWOIAL=z`1Fu)7 zp=g3Oc?iDb<(&2PQdZfPlY)csI)?Jo;ITERJBji9%}~DcYQYQhAKKA*HDLfB&{4Qg z2ef3Zo+PiLW8SUNp{|!*+uRA7k5({0vM&?HO?Q3)?Rx?_1}l!S$lJU665$_|7onYN z7JQ6772Ei{&?ha@ByFFESw?wFwH>rx-=2J@d`IQ^{Jj^s+0^~8O){tZ!0SYiSZ4o@ zps)AovPaSKc6GgjGDo#Fssrt-pi7T|PbJ_~o?cz_{ z$T6uW8^@Gm3!YKq|56}JbK}1a;~)6>)Tw~S>H4>w=NEG^)-HYWX#I1# zZbAD}@Y(^G66kG}{-R%Zw`2Wz{nqbsr3h6rMmt^j&|9ff^FT5 zzS@^7d8g}y+BH${d<_IGslAOBnl8S3so+zX)tZQp;PYYW-`X7=CV-17PK z4P-889~Ewl|1k(VfOhKDF_r~S&)wc-*N_HMt^eVeU)15kHPW4HU%>Z=TFiP|IpVlJAa3Hzg@l=CqaldaSzgH#YsRq_IJFu^Lp6l ze=xBe3wVw;@Js_e9AaYmTojYOBjTH1hVTE7x3@MnRLrCp*C{ZutjkYW;t;oyPp{*( zyUdt4c#aWt3aFK7nNW?N*U|AI9(mebbiY3gPI2qz7gW~#>4PE3rsBgb<{KK6k&-IB{z9^{VP6N z%5_~&-cc~E)KxNFb1-Iuu!Ap`GRv-u!!7itZh@?b|M|Lvb1!@Vbr$6rnB_oc%sgS^ z=y>_m48U?t4OTM7oH)2<>)l-HE1;!(LEN$28;3_9f%*Vg(Itf=xIymg3}EBvkcZ$5 zgLfQUv-L-}CmCO+9i-0wu@PQ5XWUq$ORDd_&akZ!K6wQ47mn>Ta9euzKdiey2Q-g) zxR+`~k@|r?_xZX6eL}gO&Imoy1|M~%Mn9_ejndvIFXfE8fWN-dm%2@dm6$90FzhV< zlHL|oR{o}KK7jR5WJ3QR(EZaW9M+L`FiyD7NPS<2t2n9KV0$+d(#8V4Udp_qMV}8T ze8d@C$NH7noRZ!73D^+&0*o6!AvpE&u>GtDD{Z75$X^&r8#gLjl(Rm9b+vXR_F*25 zv$?=u$+&qygE8-aRS=u0kAT7c7KanU4 zZSPUUXI4so!#QJRuDyJ|(D89-_sjw4z$^U59KBYsJ8ll+hQC{tpEOBZ@yvo()@1CB zyv2^aFwA?p2Jt+~LH`Q6_G94E77lAPNUH#Q9&1OXAFawynxq}#1>V*`C1?Ifj|&Qq zdbzUaIqN3iKUYhW`;)O1y7tL>_^rrKTBHeHfu8tdjy>}^><6=(S^FXj_iV;FijI-Q zeC`D8|J2H_Xfwup2y?tN{I)~rG$TK8VOy6fTD5Uwr8DG>#Mpnb+;7c_^C$K`yBcS3 zyvyJ^$9oabs~HD;Gww;d%zb?Ta=XaMgK*gj-bC=dg2>Lip8SL*4sin-^qEL=0Es-v zD~PpL^&h;91C)_(FetO|D>&G19OG5ssD1}I^?n~xPti{O1nc20yid87cW~gf1od2B z0X%K1@mtK<=VXkcZJ?zut$D?*?tNXm`#n_O6&l|3U7>1>VCwD(@g+=N<#yVn7>yrSUp+@A2b1Qj^2- zdwAo-HU%>h$1cKNuOThc6#C4`le{SdWuZ*IZ00cZdceiLpu_XMRI$Hf8uu~1zFwKJ zF3jic7%v-os*R`l3fCU`Rbo`B!piWRXkj6!SCulj6({{Y#V@*gO($gk&P>c8zauE02VpdW|BV~jeU z^_ueEbor%B{loi{vGJd6V;db#HQ!nWq> zZD&%ZKXD>$e!TR&`LWphqn*Y~$hlv12J2-Lz87Qv5AKi5#X%kBMd{W4A>c&G)9(AD zC>~N5zQ0pr%>M($+~2{+*%ZvpnBCurtWmjse;UZuEqB1-_zCfYyWegfcKq*8YwoYJ z7Hl?azY+K!F8_x$ literal 0 HcmV?d00001 diff --git a/mkdocs.yml b/mkdocs.yml index da26450b..3fcaa501 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -1,6 +1,7 @@ site_name: Snowfakery documentation site_url: "" theme: readthedocs +theme_dir: custom_theme repo_url: https://github.com/SFDO-Tooling/Snowfakery/ nav: - index.md From ace0f77f59a72f8f83e7185ac67576ee23009b3c Mon Sep 17 00:00:00 2001 From: Paul Prescod Date: Mon, 14 Jun 2021 01:37:46 -0700 Subject: [PATCH 11/53] Better, unified docs on faking --- .gitignore | 2 + docs/fakedata.md | 7483 ----------------- examples/faker_in_formula.recipe.yml | 3 + examples/parameters.recipe.yml | 3 + examples/parameters_block.recipe.yml | 6 + examples/salesforce/simple_account.recipe.yml | 18 + .../simple_account_french.recipe.yml | 20 + .../simple_account_random.recipe.yml | 26 + snowfakery/fakedata/fake_data_generator.py | 8 + .../faker_docs_utils/fakedata_header_full.md | 165 + .../faker_docs_utils/fakedata_header_short.md | 10 + tools/faker_docs_utils/faker_markdown.py | 22 +- .../mkdocs_plugins/main_mkdocs_plugin.py | 6 +- 13 files changed, 271 insertions(+), 7501 deletions(-) delete mode 100644 docs/fakedata.md create mode 100644 examples/faker_in_formula.recipe.yml create mode 100644 examples/parameters.recipe.yml create mode 100644 examples/parameters_block.recipe.yml create mode 100644 examples/salesforce/simple_account.recipe.yml create mode 100644 examples/salesforce/simple_account_french.recipe.yml create mode 100644 examples/salesforce/simple_account_random.recipe.yml create mode 100644 tools/faker_docs_utils/fakedata_header_full.md create mode 100644 tools/faker_docs_utils/fakedata_header_short.md diff --git a/.gitignore b/.gitignore index b8c2bc1c..a5dd4cf3 100644 --- a/.gitignore +++ b/.gitignore @@ -14,6 +14,8 @@ dist/ docs/api/ docs/_build/ docs/fakedata +docs/fakedata.md +docs/locales.md .eggs/ .idea/ .tox/ diff --git a/docs/fakedata.md b/docs/fakedata.md deleted file mode 100644 index 40ec6865..00000000 --- a/docs/fakedata.md +++ /dev/null @@ -1,7483 +0,0 @@ -# Fake Data: en_US - -The basic concepts of fake data are described in -the [main docs](index.md#fake-data). - -Current Locale: en_US (United States) - - -Our fake data can be localized to many languages. We have -[detailed docs](https://snowfakery.readthedocs.io/en/feature-fake-data-docs/locales.html) -about the other languages. - -[TOC] - -## Commonly Used - -### Salesforce Fakers - -#### fake: Email - -Email address using one of the "example" domains - -Aliases: email - -Source: [snowfakery](https://github.com/SFDO-Tooling/Snowfakery/tree/main/snowfakery/fakedata/fake_data_generator.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.Email}} - block_example: - fake: Email - -Outputs: - - Example(id=1, inline_example=dakotagaines@example.org, block_example=thurst@example.net) - -### Address Fakers - -#### fake: AdministrativeUnit - -Aliases: administrative_unit, administrativeunit - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/address/en_US/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.AdministrativeUnit}} - block_example: - fake: AdministrativeUnit - -Outputs: - - Example(id=1, inline_example=North Carolina, block_example=New York) - -#### fake: BuildingNumber - -Example: '791' - -Aliases: building_number, buildingnumber - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/address/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.BuildingNumber}} - block_example: - fake: BuildingNumber - -Outputs: - - Example(id=1, inline_example=15781, block_example=6593) - -#### fake: City - -Example: 'Sashabury' - -Aliases: city - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/address/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.City}} - block_example: - fake: City - -Outputs: - - Example(id=1, inline_example=New Raymondside, block_example=West Edgar) - -#### fake: Country - -Aliases: country - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/address/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.Country}} - block_example: - fake: Country - -Outputs: - - Example(id=1, inline_example=Armenia, block_example=Eritrea) - -#### fake: CountryCode - -Aliases: country_code, countrycode - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/address/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.CountryCode}} - block_example: - fake: CountryCode - -Outputs: - - Example(id=1, inline_example=SE, block_example=RU) - -#### fake: CurrentCountry - -Aliases: current_country, currentcountry - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/address/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.CurrentCountry}} - block_example: - fake: CurrentCountry - -Outputs: - - Example(id=1, inline_example=United States, block_example=United States) - -#### fake: CurrentCountryCode - -Aliases: current_country_code, currentcountrycode - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/address/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.CurrentCountryCode}} - block_example: - fake: CurrentCountryCode - -Outputs: - - Example(id=1, inline_example=US, block_example=US) - -#### fake: Postalcode - -Aliases: postalcode - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/address/en_US/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.Postalcode}} - block_example: - fake: Postalcode - -Outputs: - - Example(id=1, inline_example=67514, block_example=64192) - -#### fake: State - -Aliases: state - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/address/en_US/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.State}} - block_example: - fake: State - -Outputs: - - Example(id=1, inline_example=North Carolina, block_example=New York) - -#### fake: StreetAddress - -Example: '791 Crist Parks' - -Aliases: street_address, streetaddress - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/address/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.StreetAddress}} - block_example: - fake: StreetAddress - -Outputs: - - Example(id=1, inline_example=93328 Ortiz Common, block_example=714 Knox Crossing Suite 839) - -### Company Fakers - -#### fake: CatchPhrase - -Example: 'Robust full-range hub' - -Aliases: catch_phrase, catchphrase - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/company/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.CatchPhrase}} - block_example: - fake: CatchPhrase - -Outputs: - - Example(id=1, inline_example=Devolved executive challenge, block_example=Versatile bandwidth-monitored process improvement) - -#### fake: Company - -Example: 'Acme Ltd' - -Aliases: company - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/company/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.Company}} - block_example: - fake: Company - -Outputs: - - Example(id=1, inline_example=Krause-Wilcox, block_example=Bautista, Callahan and Davila) - -### Date_Time Fakers - -#### fake: Time - -Get a time string (24h format by default) -:param pattern format -Example: '15:02:34' - -Aliases: time - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/date_time/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.Time}} - block_example: - fake: Time - -Outputs: - - Example(id=1, inline_example=19:09:38, block_example=16:37:16) - -#### fake: Year - -Aliases: year - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/date_time/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.Year}} - block_example: - fake: Year - -Outputs: - - Example(id=1, inline_example=2003, block_example=1997) - -### Lorem Fakers - -#### fake: Paragraph - -Generate a paragraph. - -The ``nb_sentences`` argument controls how many sentences the paragraph -will contain, and setting ``variable_nb_sentences`` to ``False`` will -generate the exact amount, while setting it to ``True`` (default) will -generate a random amount (+/-40%, minimum of 1) using -|randomize_nb_elements|. - -Under the hood, |sentences| is used to generate the sentences, so the -argument ``ext_word_list`` works in the same way here as it would in -that method. - - - - -ext_word_list=['abc', 'def', 'ghi', 'jkl'] - -Aliases: paragraph - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/lorem/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.Paragraph(nb_sentences=5)}} - block_example: - fake.Paragraph: - nb_sentences: 5 - -Outputs: - - Example(id=1, inline_example=Others kind company likely. Tonight themselves true power home price. Night actually score from. Name care several., block_example=Particular pull opportunity throughout take car. Hold increase practice ability court. Civil development large report purpose themselves. I reduce industry. Close ask reduce. Month maintain no sense this manager fine.) - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.Paragraph(nb_sentences=5, variable_nb_sentences=False)}} - block_example: - fake.Paragraph: - nb_sentences: 5 - variable_nb_sentences: false - -Outputs: - - Example(id=1, inline_example=Anyone state wind indeed nature white without. Would I question first. Add senior woman put partner. Budget power them evidence without. Little type physical against., block_example=Son break either president stage population boy. Everything affect American race. Fire happen nothing support suffer which parent. Republican total policy head Mrs debate onto. Catch even front.) - -#### fake: Sentence - -Generate a sentence. - -The ``nb_words`` argument controls how many words the sentence will -contain, and setting ``variable_nb_words`` to ``False`` will generate -the exact amount, while setting it to ``True`` (default) will generate -a random amount (+/-40%, minimum of 1) using |randomize_nb_elements|. - -Under the hood, |words| is used to generate the words, so the argument -``ext_word_list`` works in the same way here as it would in that method. - - - - -ext_word_list=['abc', 'def', 'ghi', 'jkl'] - -Aliases: sentence - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/lorem/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.Sentence(nb_words=10)}} - block_example: - fake.Sentence: - nb_words: 10 - -Outputs: - - Example(id=1, inline_example=Feeling fact by four two data son., block_example=Onto knowledge other his offer face country cost party prevent live bed serious.) - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.Sentence(nb_words=10, variable_nb_words=False)}} - block_example: - fake.Sentence: - nb_words: 10 - variable_nb_words: false - -Outputs: - - Example(id=1, inline_example=Theory type successful together type music hospital relate every speech., block_example=Support time operation wear often late produce you true soldier.) - -#### fake: Text - -Generate a text string. - -The ``max_nb_chars`` argument controls the approximate number of -characters the text string will have, and depending on its value, this -method may use either |words|, |sentences|, or |paragraphs| for text -generation. The ``ext_word_list`` argument works in exactly the same way -it would in any of those methods. - -Aliases: text - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/lorem/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.Text(max_nb_chars=20)}} - block_example: - fake.Text: - max_nb_chars: 20 - -Outputs: - - Example(id=1, inline_example=Book pick method., block_example=Organization into.) - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.Text(max_nb_chars=80)}} - block_example: - fake.Text: - max_nb_chars: 80 - -Outputs: - - Example(id=1, inline_example=There many true follow marriage material. Myself use act relationship section., block_example=Family relationship like son might trip at candidate.) - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.Text(max_nb_chars=160)}} - block_example: - fake.Text: - max_nb_chars: 160 - -Outputs: - - Example(id=1, inline_example=Measure too maybe off question source. Wrong section town deal movement out stay lot. Parent do ten after those scientist., block_example=Individual man tell response purpose character would. - Partner hit another. Sing after our car food record power. Himself simply make thing particular.) - -#### fake: Word - -Generate a word. - -This method uses |words| under the hood with the ``nb`` argument set to -``1`` to generate the result. - -Aliases: word - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/lorem/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.Word}} - block_example: - fake: Word - -Outputs: - - Example(id=1, inline_example=interview, block_example=why) - -### Person Fakers - -#### fake: FirstName - -Aliases: first_name, firstname - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/person/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.FirstName}} - block_example: - fake: FirstName - -Outputs: - - Example(id=1, inline_example=Danielle, block_example=Vernon) - -#### fake: FirstNameFemale - -Aliases: first_name_female, firstnamefemale - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/person/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.FirstNameFemale}} - block_example: - fake: FirstNameFemale - -Outputs: - - Example(id=1, inline_example=Krista, block_example=Jasmine) - -#### fake: FirstNameMale - -Aliases: first_name_male, firstnamemale - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/person/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.FirstNameMale}} - block_example: - fake: FirstNameMale - -Outputs: - - Example(id=1, inline_example=Logan, block_example=Jared) - -#### fake: FirstNameNonbinary - -Aliases: first_name_nonbinary, firstnamenonbinary - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/person/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.FirstNameNonbinary}} - block_example: - fake: FirstNameNonbinary - -Outputs: - - Example(id=1, inline_example=Danielle, block_example=Vernon) - -#### fake: LastName - -Aliases: last_name, lastname - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/person/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.LastName}} - block_example: - fake: LastName - -Outputs: - - Example(id=1, inline_example=Goodwin, block_example=Hendrix) - -#### fake: Name - -Example: 'John Doe' - -Aliases: name - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/person/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.Name}} - block_example: - fake: Name - -Outputs: - - Example(id=1, inline_example=Morgan Escobar, block_example=Jay Coleman II) - -#### fake: NameFemale - -Aliases: name_female, namefemale - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/person/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.NameFemale}} - block_example: - fake: NameFemale - -Outputs: - - Example(id=1, inline_example=Morgan Escobar DDS, block_example=Briana Moon MD) - -#### fake: NameMale - -Aliases: name_male, namemale - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/person/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.NameMale}} - block_example: - fake: NameMale - -Outputs: - - Example(id=1, inline_example=Ruben Escobar III, block_example=Chris Moon II) - -### Phone_Number Fakers - -#### fake: PhoneNumber - -Aliases: phone_number, phonenumber - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/phone_number/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.PhoneNumber}} - block_example: - fake: PhoneNumber - -Outputs: - - Example(id=1, inline_example=484-185-8398, block_example=001-471-965-9342) - -## Rarely Used - -### Salesforce Fakers - -#### fake: UserName - -Salesforce-style username in the form of an email address - -Aliases: user_name, username - -Source: [snowfakery](https://github.com/SFDO-Tooling/Snowfakery/tree/main/snowfakery/fakedata/fake_data_generator.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.UserName}} - block_example: - fake: UserName - -Outputs: - - Example(id=1, inline_example=Kevin_Dodson_fb3675b8-9cde-43e6-8870-e15c2fcd81b5@email-47.sullivan.com, block_example=James_Terrell_e5eeac76-148b-4758-97ab-792809e469e6@email-86.morrow.com) - -#### fake: Alias - -Salesforce-style 8-character alias - -Aliases: alias - -Source: [snowfakery](https://github.com/SFDO-Tooling/Snowfakery/tree/main/snowfakery/fakedata/fake_data_generator.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.Alias}} - block_example: - fake: Alias - -Outputs: - - Example(id=1, inline_example=Martin, block_example=Priscill) - -#### fake: RealisticMaybeRealEmail - -Like fake: email except that the email domain may be real and therefore -the email address itself may be real. Use with caution, you might -accidentally email strangers!!! - -Aliases: realistic_maybe_real_email, realisticmayberealemail - -Source: [snowfakery](https://github.com/SFDO-Tooling/Snowfakery/tree/main/snowfakery/fakedata/fake_data_generator.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.RealisticMaybeRealEmail}} - block_example: - fake: RealisticMaybeRealEmail - -Outputs: - - Example(id=1, inline_example=holly75@gmail.com, block_example=langpenny@hotmail.com) - -### Address Fakers - -#### fake: Address - -Example: '791 Crist Parks, Sashabury, IL 86039-9874' - -Aliases: address - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/address/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.Address}} - block_example: - fake: Address - -Outputs: - - Example(id=1, inline_example=848 Martin Springs Suite 947 - Claystad, MD 80819, block_example=533 Sean Crescent Apt. 525 - Gouldton, WY 19684) - -#### fake: CityPrefix - -Aliases: city_prefix, cityprefix - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/address/en_US/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.CityPrefix}} - block_example: - fake: CityPrefix - -Outputs: - - Example(id=1, inline_example=West, block_example=New) - -#### fake: CitySuffix - -Example: 'town' - -Aliases: city_suffix, citysuffix - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/address/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.CitySuffix}} - block_example: - fake: CitySuffix - -Outputs: - - Example(id=1, inline_example=fort, block_example=furt) - -#### fake: MilitaryApo - -Example: 'PSC 5394 Box 3492 - -Aliases: military_apo, militaryapo - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/address/en_US/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.MilitaryApo}} - block_example: - fake: MilitaryApo - -Outputs: - - Example(id=1, inline_example=PSC 8016, Box 0975, block_example=PSC 3513, Box 9332) - -#### fake: MilitaryDpo - -Example: 'Unit 3333 Box 9342' - -Aliases: military_dpo, militarydpo - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/address/en_US/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.MilitaryDpo}} - block_example: - fake: MilitaryDpo - -Outputs: - - Example(id=1, inline_example=Unit 8016 Box 0975, block_example=Unit 3513 Box 9332) - -#### fake: MilitaryShip - -Example: 'USS' - -Aliases: military_ship, militaryship - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/address/en_US/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.MilitaryShip}} - block_example: - fake: MilitaryShip - -Outputs: - - Example(id=1, inline_example=USCGC, block_example=USNV) - -#### fake: MilitaryState - -Example: 'APO' - -Aliases: military_state, militarystate - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/address/en_US/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.MilitaryState}} - block_example: - fake: MilitaryState - -Outputs: - - Example(id=1, inline_example=AA, block_example=AA) - -#### fake: PostalcodeInState - -Aliases: postalcode_in_state, postalcodeinstate - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/address/en_US/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.PostalcodeInState}} - block_example: - fake: PostalcodeInState - -Outputs: - - Example(id=1, inline_example=97914, block_example=62068) - -#### fake: PostalcodePlus4 - -Aliases: postalcode_plus4, postalcodeplus4 - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/address/en_US/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.PostalcodePlus4}} - block_example: - fake: PostalcodePlus4 - -Outputs: - - Example(id=1, inline_example=76966-3579, block_example=66651-2282) - -#### fake: Postcode - -Aliases: postcode - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/address/en_US/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.Postcode}} - block_example: - fake: Postcode - -Outputs: - - Example(id=1, inline_example=67514, block_example=64192) - -#### fake: PostcodeInState - -:returns: A random postcode within the provided state abbreviation - -:param state_abbr: A state abbreviation - -Aliases: postcode_in_state, postcodeinstate - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/address/en_US/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.PostcodeInState}} - block_example: - fake: PostcodeInState - -Outputs: - - Example(id=1, inline_example=97914, block_example=62068) - -#### fake: SecondaryAddress - -Aliases: secondary_address, secondaryaddress - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/address/en_US/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.SecondaryAddress}} - block_example: - fake: SecondaryAddress - -Outputs: - - Example(id=1, inline_example=Suite 115, block_example=Suite 815) - -#### fake: StateAbbr - -:returns: A random state or territory abbreviation. - -:param include_territories: If True, territories will be included. -If False, only states will be returned. - -Aliases: state_abbr, stateabbr - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/address/en_US/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.StateAbbr}} - block_example: - fake: StateAbbr - -Outputs: - - Example(id=1, inline_example=ME, block_example=MI) - -#### fake: StreetName - -Example: 'Crist Parks' - -Aliases: street_name, streetname - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/address/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.StreetName}} - block_example: - fake: StreetName - -Outputs: - - Example(id=1, inline_example=Dwayne River, block_example=Krause Place) - -#### fake: StreetSuffix - -Example: 'Avenue' - -Aliases: street_suffix, streetsuffix - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/address/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.StreetSuffix}} - block_example: - fake: StreetSuffix - -Outputs: - - Example(id=1, inline_example=Green, block_example=Pass) - -#### fake: Zipcode - -Aliases: zipcode - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/address/en_US/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.Zipcode}} - block_example: - fake: Zipcode - -Outputs: - - Example(id=1, inline_example=67514, block_example=64192) - -#### fake: ZipcodeInState - -Aliases: zipcode_in_state, zipcodeinstate - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/address/en_US/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.ZipcodeInState}} - block_example: - fake: ZipcodeInState - -Outputs: - - Example(id=1, inline_example=97914, block_example=62068) - -#### fake: ZipcodePlus4 - -Aliases: zipcode_plus4, zipcodeplus4 - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/address/en_US/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.ZipcodePlus4}} - block_example: - fake: ZipcodePlus4 - -Outputs: - - Example(id=1, inline_example=76966-3579, block_example=66651-2282) - -### Automotive Fakers - -#### fake: LicensePlate - -Generate a license plate. - -Aliases: license_plate, licenseplate - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/automotive/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.LicensePlate}} - block_example: - fake: LicensePlate - -Outputs: - - Example(id=1, inline_example=938 NK7, block_example=40-Q801) - -### Bank Fakers - -#### fake: BankCountry - -Generate the bank provider's ISO 3166-1 alpha-2 country code. - -Aliases: bank_country, bankcountry - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/bank/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.BankCountry}} - block_example: - fake: BankCountry - -Outputs: - - Example(id=1, inline_example=GB, block_example=GB) - -#### fake: Bban - -Generate a Basic Bank Account Number (BBAN). - -Aliases: bban - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/bank/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.Bban}} - block_example: - fake: Bban - -Outputs: - - Example(id=1, inline_example=FBTV47112201868483, block_example=GVSN94775159179533) - -#### fake: Iban - -Generate an International Bank Account Number (IBAN). - -Aliases: iban - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/bank/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.Iban}} - block_example: - fake: Iban - -Outputs: - - Example(id=1, inline_example=GB68FBTV47112201868483, block_example=GB71GVSN94775159179533) - -#### fake: Swift - -Generate a SWIFT code. - -SWIFT codes, reading from left to right, are composed of a 4 alphabet -character bank code, a 2 alphabet character country code, a 2 -alphanumeric location code, and an optional 3 alphanumeric branch code. -This means SWIFT codes can only have 8 or 11 characters, so the value of -``length`` can only be ``None`` or the integers ``8`` or ``11``. If the -value is ``None``, then a value of ``8`` or ``11`` will randomly be -assigned. - -Because all 8-digit SWIFT codes already refer to the primary branch or -office, the ``primary`` argument only has an effect if the value of -``length`` is ``11``. If ``primary`` is ``True`` and ``length`` is -``11``, the 11-digit SWIFT codes generated will always end in ``'XXX'`` -to denote that they belong to primary branches/offices. - -For extra authenticity, localized providers may opt to include SWIFT -bank codes, location codes, and branch codes used in their respective -locales. If ``use_dataset`` is ``True``, this method will generate SWIFT -codes based on those locale-specific codes if included. If those codes -were not included, then it will behave as if ``use_dataset`` were -``False``, and in that mode, all those codes will just be randomly -generated as per the specification. - -Aliases: swift - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/bank/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.Swift}} - block_example: - fake: Swift - -Outputs: - - Example(id=1, inline_example=VKPRGBGW, block_example=KTUGGB9427Q) - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.Swift(length=8)}} - block_example: - fake.Swift: - length: 8 - -Outputs: - - Example(id=1, inline_example=BZRAGBFZ, block_example=WZVUGBA5) - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.Swift(length=8, use_dataset=True)}} - block_example: - fake.Swift: - length: 8 - use_dataset: true - -Outputs: - - Example(id=1, inline_example=KHXKGBEM, block_example=SHHZGBJ8) - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.Swift(length=11)}} - block_example: - fake.Swift: - length: 11 - -Outputs: - - Example(id=1, inline_example=OCCKGB65GT9, block_example=JWDRGBV8N9S) - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.Swift(length=11, primary=True)}} - block_example: - fake.Swift: - length: 11 - primary: true - -Outputs: - - Example(id=1, inline_example=OCTZGBYUXXX, block_example=SHJFGBMLXXX) - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.Swift(length=11, use_dataset=True)}} - block_example: - fake.Swift: - length: 11 - use_dataset: true - -Outputs: - - Example(id=1, inline_example=BTVIGB4EFIJ, block_example=BCWRGBZ7R7P) - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.Swift(length=11, primary=True, use_dataset=True)}} - block_example: - fake.Swift: - length: 11 - primary: true - use_dataset: true - -Outputs: - - Example(id=1, inline_example=GVSNGBR2XXX, block_example=PVUWGBWFXXX) - -#### fake: Swift11 - -Generate an 11-digit SWIFT code. - -This method uses |swift| under the hood with the ``length`` argument set -to ``11``. If ``primary`` is set to ``True``, the SWIFT code will always -end with ``'XXX'``. All 11-digit SWIFT codes use this convention to -refer to the primary branch/office. - -Aliases: swift11 - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/bank/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.Swift11}} - block_example: - fake: Swift11 - -Outputs: - - Example(id=1, inline_example=TPKHGBUEMOP, block_example=ZEZRGB2FFU6) - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.Swift11(use_dataset=True)}} - block_example: - fake.Swift11: - use_dataset: true - -Outputs: - - Example(id=1, inline_example=PDJRGBSH9V8, block_example=GZTRGBS2FYU) - -#### fake: Swift8 - -Generate an 8-digit SWIFT code. - -This method uses |swift| under the hood with the ``length`` argument set -to ``8`` and with the ``primary`` argument omitted. All 8-digit SWIFT -codes already refer to the primary branch/office. - -Aliases: swift8 - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/bank/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.Swift8}} - block_example: - fake: Swift8 - -Outputs: - - Example(id=1, inline_example=XCVKGB49, block_example=DLNKGBN9) - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.Swift8(use_dataset=True)}} - block_example: - fake.Swift8: - use_dataset: true - -Outputs: - - Example(id=1, inline_example=POQIGBD9, block_example=ACXMGBA5) - -### Barcode Fakers - -#### fake: Ean - -Generate an EAN barcode of the specified ``length``. - -The value of ``length`` can only be ``8`` or ``13`` (default) which will -create an EAN-8 or an EAN-13 barcode respectively. - -If a value for ``prefixes`` is specified, the result will begin with one -of the sequences in ``prefixes``. - -Aliases: ean - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/barcode/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.Ean(length=13)}} - block_example: - fake.Ean: - length: 13 - -Outputs: - - Example(id=1, inline_example=1858398947198, block_example=6593423209470) - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.Ean(length=8)}} - block_example: - fake.Ean: - length: 8 - -Outputs: - - Example(id=1, inline_example=11220183, block_example=68483395) - -#### fake: Ean13 - -Generate an EAN-13 barcode. - -If ``leading_zero`` is ``True``, the leftmost digit of the barcode will -be set to ``0``. If ``False``, the leftmost digit cannot be ``0``. If -``None`` (default), the leftmost digit can be any digit. - -If a value for ``prefixes`` is specified, the result will begin with one -of the sequences in ``prefixes`` and will ignore ``leading_zero``. - -This method uses the standard barcode provider's |ean13| under the -hood with the ``prefixes`` argument set to the correct value to attain -the behavior described above. - -.. note:: -EAN-13 barcode that starts with a zero can be converted to UPC-A -by dropping the leading zero. This may cause problems with readers -that treat all of these code as UPC-A codes and drop the first digit -when reading it. - -You can set the argument ``prefixes`` ( or ``leading_zero`` for -convenience) explicitly to avoid or to force the generated barcode to -start with a zero. You can also generate actual UPC-A barcode with -|EnUsBarcodeProvider.upc_a|. - -Aliases: ean13 - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/barcode/en_US/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.Ean13}} - block_example: - fake: Ean13 - -Outputs: - - Example(id=1, inline_example=1858398947198, block_example=6593423209470) - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.Ean13(leading_zero=False)}} - block_example: - fake.Ean13: - leading_zero: false - -Outputs: - - Example(id=1, inline_example=2220186848335, block_example=5751591795336) - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.Ean13(leading_zero=True)}} - block_example: - fake.Ean13: - leading_zero: true - -Outputs: - - Example(id=1, inline_example=135256012306, block_example=0139916151091) - -#### fake: Ean8 - -Generate an EAN-8 barcode. - -This method uses |ean| under the hood with the ``length`` argument -explicitly set to ``8``. - -If a value for ``prefixes`` is specified, the result will begin with one -of the sequences in ``prefixes``. - -Aliases: ean8 - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/barcode/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.Ean8}} - block_example: - fake: Ean8 - -Outputs: - - Example(id=1, inline_example=80160977, block_example=53513939) - -#### fake: LocalizedEan - -Generate a localized EAN barcode of the specified ``length``. - -The value of ``length`` can only be ``8`` or ``13`` (default) which will -create an EAN-8 or an EAN-13 barcode respectively. - -This method uses the standard barcode provider's |ean| under the hood -with the ``prefixes`` argument explicitly set to ``local_prefixes`` of -a localized barcode provider implementation. - -Aliases: localized_ean, localizedean - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/barcode/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.LocalizedEan}} - block_example: - fake: LocalizedEan - -Outputs: - - Example(id=1, inline_example=301609753510, block_example=0432871158717) - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.LocalizedEan(length=13)}} - block_example: - fake.LocalizedEan: - length: 13 - -Outputs: - - Example(id=1, inline_example=118583989473, block_example=0759342320948) - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.LocalizedEan(length=8)}} - block_example: - fake.LocalizedEan: - length: 8 - -Outputs: - - Example(id=1, inline_example=10220184, block_example=13483395) - -#### fake: LocalizedEan13 - -Generate a localized EAN-13 barcode. - -This method uses |localized_ean| under the hood with the ``length`` -argument explicitly set to ``13``. - -Aliases: localized_ean13, localizedean13 - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/barcode/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.LocalizedEan13}} - block_example: - fake: LocalizedEan13 - -Outputs: - - Example(id=1, inline_example=948418583985, block_example=0019659342324) - -#### fake: LocalizedEan8 - -Generate a localized EAN-8 barcode. - -This method uses |localized_ean| under the hood with the ``length`` -argument explicitly set to ``8``. - -Aliases: localized_ean8, localizedean8 - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/barcode/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.LocalizedEan8}} - block_example: - fake: LocalizedEan8 - -Outputs: - - Example(id=1, inline_example=7016097, block_example=03513934) - -#### fake: UpcA - -Generate a 12-digit UPC-A barcode. - -The value of ``upc_ae_mode`` controls how barcodes will be generated. If -``False`` (default), barcodes are not guaranteed to have a UPC-E -equivalent. In this mode, the method uses |EnUsBarcodeProvider.ean13| -under the hood, and the values of ``base`` and ``number_system_digit`` -will be ignored. - -If ``upc_ae_mode`` is ``True``, the resulting barcodes are guaranteed to -have a UPC-E equivalent, and the values of ``base`` and -``number_system_digit`` will be used to control what is generated. - -Under this mode, ``base`` is expected to have a 6-digit string value. If -any other value is supplied, a random 6-digit string will be used -instead. As for ``number_system_digit``, the expected value is a ``0`` -or a ``1``. If any other value is provided, this method will randomly -choose from the two. - -.. important:: -When ``upc_ae_mode`` is enabled, you might encounter instances where -different values of ``base`` (e.g. ``'120003'`` and ``'120004'``) -produce the same UPC-A barcode. This is normal, and the reason lies -within the whole conversion process. To learn more about this and -what ``base`` and ``number_system_digit`` actually represent, please -refer to |EnUsBarcodeProvider.upc_e|. - -Aliases: upc_a, upca - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/barcode/en_US/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.UpcA}} - block_example: - fake: UpcA - -Outputs: - - Example(id=1, inline_example=604876475933, block_example=219489241150) - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.UpcA(upc_ae_mode=True, number_system_digit=0)}} - block_example: - fake.UpcA: - upc_ae_mode: true - number_system_digit: 0 - -Outputs: - - Example(id=1, inline_example=81565000094, block_example=038770000081) - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.UpcA(upc_ae_mode=True, number_system_digit=1)}} - block_example: - fake.UpcA: - upc_ae_mode: true - number_system_digit: 1 - -Outputs: - - Example(id=1, inline_example=108000000164, block_example=197100005353) - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.UpcA(upc_ae_mode=True, base='123456', number_system_digit=0)}} - block_example: - fake.UpcA: - upc_ae_mode: true - base: '123456' - number_system_digit: 0 - -Outputs: - - Example(id=1, inline_example=12345000065, block_example=039332000082) - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.UpcA(upc_ae_mode=True, base='120003', number_system_digit=0)}} - block_example: - fake.UpcA: - upc_ae_mode: true - base: '120003' - number_system_digit: 0 - -Outputs: - - Example(id=1, inline_example=12000000003, block_example=071158000075) - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.UpcA(upc_ae_mode=True, base='120004', number_system_digit=0)}} - block_example: - fake.UpcA: - upc_ae_mode: true - base: '120004' - number_system_digit: 0 - -Outputs: - - Example(id=1, inline_example=12000000003, block_example=014841000082) - -#### fake: UpcE - -Generate an 8-digit UPC-E barcode. - -UPC-E barcodes can be expressed in 6, 7, or 8-digit formats, but this -method uses the 8 digit format, since it is trivial to convert to the -other two formats. The first digit (starting from the left) is -controlled by ``number_system_digit``, and it can only be a ``0`` or a -``1``. The last digit is the check digit that is inherited from the -UPC-E barcode's UPC-A equivalent. The middle six digits are collectively -referred to as the ``base`` (for a lack of a better term). - -On that note, this method uses ``base`` and ``number_system_digit`` to -first generate a UPC-A barcode for the check digit, and what happens -next depends on the value of ``safe_mode``. The argument ``safe_mode`` -exists, because there are some UPC-E values that share the same UPC-A -equivalent. For example, any UPC-E barcode of the form ``abc0000d``, -``abc0003d``, and ``abc0004d`` share the same UPC-A value -``abc00000000d``, but that UPC-A value will only convert to ``abc0000d`` -because of (a) how UPC-E is just a zero-suppressed version of UPC-A and -(b) the rules around the conversion. - -If ``safe_mode`` is ``True`` (default), this method performs another set -of conversions to guarantee that the UPC-E barcodes generated can be -converted to UPC-A, and that UPC-A barcode can be converted back to the -original UPC-E barcode. Using the example above, even if the bases -``120003`` or ``120004`` are used, the resulting UPC-E barcode will -always use the base ``120000``. - -If ``safe_mode`` is ``False``, then the ``number_system_digit``, -``base``, and the computed check digit will just be concatenated -together to produce the UPC-E barcode, and attempting to convert the -barcode to UPC-A and back again to UPC-E will exhibit the behavior -described above. - -Aliases: upc_e, upce - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/barcode/en_US/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.UpcE}} - block_example: - fake: UpcE - -Outputs: - - Example(id=1, inline_example=16604872, block_example=04759386) - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.UpcE(base='123456')}} - block_example: - fake.UpcE: - base: '123456' - -Outputs: - - Example(id=1, inline_example=11234562, block_example=02194899) - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.UpcE(base='123456', number_system_digit=0)}} - block_example: - fake.UpcE: - base: '123456' - number_system_digit: 0 - -Outputs: - - Example(id=1, inline_example=1234565, block_example=04115786) - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.UpcE(base='123456', number_system_digit=1)}} - block_example: - fake.UpcE: - base: '123456' - number_system_digit: 1 - -Outputs: - - Example(id=1, inline_example=11234562, block_example=11565933) - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.UpcE(base='120000', number_system_digit=0)}} - block_example: - fake.UpcE: - base: '120000' - number_system_digit: 0 - -Outputs: - - Example(id=1, inline_example=1200003, block_example=08778400) - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.UpcE(base='120003', number_system_digit=0)}} - block_example: - fake.UpcE: - base: '120003' - number_system_digit: 0 - -Outputs: - - Example(id=1, inline_example=1200003, block_example=08016946) - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.UpcE(base='120004', number_system_digit=0)}} - block_example: - fake.UpcE: - base: '120004' - number_system_digit: 0 - -Outputs: - - Example(id=1, inline_example=1200003, block_example=07535137) - -### Color Fakers - -#### fake: Color - -Generate a color in a human-friendly way. - -Under the hood, this method first creates a color represented in the HSV -color model and then converts it to the desired ``color_format``. The -argument ``hue`` controls the H value according to the following -rules: - -- If the value is a number from ``0`` to ``360``, it will serve as the H -value of the generated color. -- If the value is a tuple/list of 2 numbers from 0 to 360, the color's H -value will be randomly selected from that range. -- If the value is a valid string, the color's H value will be randomly -selected from the H range corresponding to the supplied string. Valid -values are ``'monochrome'``, ``'red'``, ``'orange'``, ``'yellow'``, -``'green'``, ``'blue'``, ``'purple'``, and ``'pink'``. - -The argument ``luminosity`` influences both S and V values and is -partially affected by ``hue`` as well. The finer details of this -relationship are somewhat involved, so please refer to the source code -instead if you wish to dig deeper. To keep the interface simple, this -argument either can be omitted or can accept the following string -values:``'bright'``, ``'dark'``, ``'light'``, or ``'random'``. - -The argument ``color_format`` controls in which color model the color is -represented. Valid values are ``'hsv'``, ``'hsl'``, ``'rgb'``, or -``'hex'`` (default). - -Aliases: color - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/color/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.Color(hue='red')}} - block_example: - fake.Color: - hue: red - -Outputs: - - Example(id=1, inline_example=#e5909b, block_example=#ff977a) - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.Color(luminosity='light')}} - block_example: - fake.Color: - luminosity: light - -Outputs: - - Example(id=1, inline_example=#f7afed, block_example=#f2de7d) - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.Color(hue='orange', luminosity='bright')}} - block_example: - fake.Color: - hue: orange - luminosity: bright - -Outputs: - - Example(id=1, inline_example=#cc9d04, block_example=#ba7112) - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.Color(hue=135, luminosity='dark', color_format='hsv')}} - block_example: - fake.Color: - hue: 135 - luminosity: dark - color_format: hsv - -Outputs: - - Example(id=1, inline_example=hsv(135, 96, 54), block_example=hsv(135, 98, 57)) - -#### fake: ColorName - -Generate a color name. - -Aliases: color_name, colorname - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/color/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.ColorName}} - block_example: - fake: ColorName - -Outputs: - - Example(id=1, inline_example=SlateBlue, block_example=PaleGreen) - -#### fake: HexColor - -Generate a color formatted as a hex triplet. - -Aliases: hex_color, hexcolor - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/color/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.HexColor}} - block_example: - fake: HexColor - -Outputs: - - Example(id=1, inline_example=#0a5d30, block_example=#42485f) - -#### fake: RgbColor - -Generate a color formatted as a comma-separated RGB value. - -Aliases: rgb_color, rgbcolor - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/color/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.RgbColor}} - block_example: - fake: RgbColor - -Outputs: - - Example(id=1, inline_example=75,158,50, block_example=37,169,241) - -#### fake: RgbCssColor - -Generate a color formatted as a CSS rgb() function. - -Aliases: rgb_css_color, rgbcsscolor - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/color/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.RgbCssColor}} - block_example: - fake: RgbCssColor - -Outputs: - - Example(id=1, inline_example=rgb(75,158,50), block_example=rgb(37,169,241)) - -#### fake: SafeColorName - -Generate a web-safe color name. - -Aliases: safe_color_name, safecolorname - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/color/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.SafeColorName}} - block_example: - fake: SafeColorName - -Outputs: - - Example(id=1, inline_example=black, block_example=olive) - -#### fake: SafeHexColor - -Generate a web-safe color formatted as a hex triplet. - -Aliases: safe_hex_color, safehexcolor - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/color/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.SafeHexColor}} - block_example: - fake: SafeHexColor - -Outputs: - - Example(id=1, inline_example=#449933, block_example=#22aaff) - -### Company Fakers - -#### fake: Bs - -Example: 'integrate extensible convergence' - -Aliases: bs - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/company/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.Bs}} - block_example: - fake: Bs - -Outputs: - - Example(id=1, inline_example=enable front-end channels, block_example=engineer mission-critical e-business) - -#### fake: CompanySuffix - -Example: 'Ltd' - -Aliases: company_suffix, companysuffix - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/company/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.CompanySuffix}} - block_example: - fake: CompanySuffix - -Outputs: - - Example(id=1, inline_example=Group, block_example=Group) - -### Credit_Card Fakers - -#### fake: CreditCardExpire - -Generate a credit card expiry date. - -This method uses |date_time_between| under the hood to generate the -expiry date, so the ``start`` and ``end`` arguments work in the same way -here as it would in that method. For the actual formatting of the expiry -date, |strftime| is used and ``date_format`` is simply passed -to that method. - -Aliases: credit_card_expire, creditcardexpire - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/credit_card/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.CreditCardExpire}} - block_example: - fake: CreditCardExpire - -Outputs: - - Example(id=1, inline_example=09/29, block_example=05/28) - -#### fake: CreditCardFull - -Generate a set of credit card details. - -Aliases: credit_card_full, creditcardfull - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/credit_card/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.CreditCardFull}} - block_example: - fake: CreditCardFull - -Outputs: - - Example(id=1, inline_example=Diners Club / Carte Blanche - Vanessa Koch - 30515917953300 01/26 - CVC: 135 - , block_example=VISA 16 digit - Ana Miranda - 4123098910139912 02/28 - CVC: 151 - ) - -#### fake: CreditCardNumber - -Generate a valid credit card number. - -Aliases: credit_card_number, creditcardnumber - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/credit_card/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.CreditCardNumber}} - block_example: - fake: CreditCardNumber - -Outputs: - - Example(id=1, inline_example=180071965934238, block_example=4947112201868487) - -#### fake: CreditCardProvider - -Generate a credit card provider name. - -Aliases: credit_card_provider, creditcardprovider - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/credit_card/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.CreditCardProvider}} - block_example: - fake: CreditCardProvider - -Outputs: - - Example(id=1, inline_example=Diners Club / Carte Blanche, block_example=Discover) - -#### fake: CreditCardSecurityCode - -Generate a credit card security code. - -Aliases: credit_card_security_code, creditcardsecuritycode - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/credit_card/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.CreditCardSecurityCode}} - block_example: - fake: CreditCardSecurityCode - -Outputs: - - Example(id=1, inline_example=924, block_example=157) - -### Currency Fakers - -#### fake: Cryptocurrency - -Aliases: cryptocurrency - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/currency/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.Cryptocurrency}} - block_example: - fake: Cryptocurrency - -Outputs: - - Example(id=1, inline_example=('USDT', 'Tether'), block_example=('ZEC', 'Zcash')) - -#### fake: CryptocurrencyCode - -Aliases: cryptocurrency_code, cryptocurrencycode - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/currency/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.CryptocurrencyCode}} - block_example: - fake: CryptocurrencyCode - -Outputs: - - Example(id=1, inline_example=USDT, block_example=ZEC) - -#### fake: CryptocurrencyName - -Aliases: cryptocurrency_name, cryptocurrencyname - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/currency/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.CryptocurrencyName}} - block_example: - fake: CryptocurrencyName - -Outputs: - - Example(id=1, inline_example=Tether, block_example=Zcash) - -#### fake: Currency - -Aliases: currency - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/currency/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.Currency}} - block_example: - fake: Currency - -Outputs: - - Example(id=1, inline_example=('SDG', 'Sudanese pound'), block_example=('NGN', 'Nigerian naira')) - -#### fake: CurrencyCode - -Aliases: currency_code, currencycode - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/currency/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.CurrencyCode}} - block_example: - fake: CurrencyCode - -Outputs: - - Example(id=1, inline_example=SDG, block_example=NGN) - -#### fake: CurrencyName - -Aliases: currency_name, currencyname - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/currency/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.CurrencyName}} - block_example: - fake: CurrencyName - -Outputs: - - Example(id=1, inline_example=Sudanese pound, block_example=Nigerian naira) - -#### fake: CurrencySymbol - -Example:: $ - -Aliases: currency_symbol, currencysymbol - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/currency/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.CurrencySymbol}} - block_example: - fake: CurrencySymbol - -Outputs: - - Example(id=1, inline_example=$, block_example=₦) - -#### fake: Pricetag - -Aliases: pricetag - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/currency/en_US/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.Pricetag}} - block_example: - fake: Pricetag - -Outputs: - - Example(id=1, inline_example=$1,784.08, block_example=$6.09) - -### Date_Time Fakers - -#### fake: AmPm - -Aliases: am_pm, ampm - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/date_time/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.AmPm}} - block_example: - fake: AmPm - -Outputs: - - Example(id=1, inline_example=PM, block_example=PM) - -#### fake: Century - -Example: 'XVII' - -Aliases: century - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/date_time/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.Century}} - block_example: - fake: Century - -Outputs: - - Example(id=1, inline_example=XVI, block_example=XIII) - -#### fake: Date - -Get a date string between January 1, 1970 and now -:param pattern format -Example: '2008-11-27' - -Aliases: date - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/date_time/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.Date}} - block_example: - fake: Date - -Outputs: - - Example(id=1, inline_example=2003-01-25, block_example=1997-07-22) - -#### fake: DateBetween - -Get a Date object based on a random date between two given dates. -Accepts date strings that can be recognized by strtotime(). - -:param start_date Defaults to 30 years ago -:param end_date Defaults to "today" -Example: Date('1999-02-02') -:return Date - -Aliases: date_between, datebetween - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/date_time/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.DateBetween}} - block_example: - fake: DateBetween - -Outputs: - - Example(id=1, inline_example=2000-04-03, block_example=2008-11-03) - -#### fake: DateBetweenDates - -Takes two Date objects and returns a random date between the two given dates. -Accepts Date or Datetime objects - -:param date_start: Date -:param date_end: Date -:return Date - -Aliases: date_between_dates, datebetweendates - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/date_time/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.DateBetweenDates}} - block_example: - fake: DateBetweenDates - -Outputs: - - Example(id=1, inline_example=2021-06-13, block_example=2021-06-13) - -#### fake: DateObject - -Get a date object between January 1, 1970 and now -Example: datetime.date(2016, 9, 20) - -Aliases: date_object, dateobject - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/date_time/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.DateObject}} - block_example: - fake: DateObject - -Outputs: - - Example(id=1, inline_example=2003-01-25, block_example=1997-07-22) - -#### fake: DateOfBirth - -Generate a random date of birth represented as a Date object, -constrained by optional miminimum_age and maximum_age -parameters. - -:param tzinfo Defaults to None. -:param minimum_age Defaults to 0. -:param maximum_age Defaults to 115. - -Example: Date('1979-02-02') -:return Date - -Aliases: date_of_birth, dateofbirth - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/date_time/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.DateOfBirth}} - block_example: - fake: DateOfBirth - -Outputs: - - Example(id=1, inline_example=1940-09-07, block_example=1975-01-12) - -#### fake: DateThisCentury - -Gets a Date object for the current century. - -:param before_today: include days in current century before today -:param after_today: include days in current century after today -Example: Date('2012-04-04') -:return Date - -Aliases: date_this_century, datethiscentury - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/date_time/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.DateThisCentury}} - block_example: - fake: DateThisCentury - -Outputs: - - Example(id=1, inline_example=2016-07-13, block_example=2013-10-11) - -#### fake: DateThisDecade - -Gets a Date object for the decade year. - -:param before_today: include days in current decade before today -:param after_today: include days in current decade after today -Example: Date('2012-04-04') -:return Date - -Aliases: date_this_decade, datethisdecade - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/date_time/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.DateThisDecade}} - block_example: - fake: DateThisDecade - -Outputs: - - Example(id=1, inline_example=2021-01-12, block_example=2020-11-10) - -#### fake: DateThisMonth - -Gets a Date object for the current month. - -:param before_today: include days in current month before today -:param after_today: include days in current month after today -:param tzinfo: timezone, instance of datetime.tzinfo subclass -Example: DateTime('2012-04-04 11:02:02') -:return DateTime - -Aliases: date_this_month, datethismonth - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/date_time/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.DateThisMonth}} - block_example: - fake: DateThisMonth - -Outputs: - - Example(id=1, inline_example=2021-06-01, block_example=2021-06-04) - -#### fake: DateThisYear - -Gets a Date object for the current year. - -:param before_today: include days in current year before today -:param after_today: include days in current year after today -Example: Date('2012-04-04') -:return Date - -Aliases: date_this_year, datethisyear - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/date_time/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.DateThisYear}} - block_example: - fake: DateThisYear - -Outputs: - - Example(id=1, inline_example=2021-04-10, block_example=2021-04-05) - -#### fake: DateTime - -Get a datetime object for a date between January 1, 1970 and now -:param tzinfo: timezone, instance of datetime.tzinfo subclass -Example: DateTime('2005-08-16 20:39:21') -:return datetime - -Aliases: date_time, datetime - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/date_time/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.DateTime}} - block_example: - fake: DateTime - -Outputs: - - Example(id=1, inline_example=2003-01-25 19:09:38, block_example=1997-07-22 16:37:16) - -#### fake: DateTimeAd - -Get a datetime object for a date between January 1, 001 and now -:param tzinfo: timezone, instance of datetime.tzinfo subclass -Example: DateTime('1265-03-22 21:15:52') -:return datetime - -Aliases: date_time_ad, datetimead - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/date_time/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.DateTimeAd}} - block_example: - fake: DateTimeAd - -Outputs: - - Example(id=1, inline_example=1877-01-02 08:15:53, block_example=0746-05-19 02:40:04) - -#### fake: DateTimeBetween - -Get a DateTime object based on a random date between two given dates. -Accepts date strings that can be recognized by strtotime(). - -:param start_date Defaults to 30 years ago -:param end_date Defaults to "now" -:param tzinfo: timezone, instance of datetime.tzinfo subclass -Example: DateTime('1999-02-02 11:42:52') -:return DateTime - -Aliases: date_time_between, datetimebetween - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/date_time/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.DateTimeBetween}} - block_example: - fake: DateTimeBetween - -Outputs: - - Example(id=1, inline_example=2000-04-05 02:13:35, block_example=2008-11-05 06:55:21) - -#### fake: DateTimeBetweenDates - -Takes two DateTime objects and returns a random datetime between the two -given datetimes. -Accepts DateTime objects. - -:param datetime_start: DateTime -:param datetime_end: DateTime -:param tzinfo: timezone, instance of datetime.tzinfo subclass -Example: DateTime('1999-02-02 11:42:52') -:return DateTime - -Aliases: date_time_between_dates, datetimebetweendates - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/date_time/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.DateTimeBetweenDates}} - block_example: - fake: DateTimeBetweenDates - -Outputs: - - Example(id=1, inline_example=2021-06-13 14:05:53, block_example=2021-06-13 14:05:53) - -#### fake: DateTimeThisCentury - -Gets a DateTime object for the current century. - -:param before_now: include days in current century before today -:param after_now: include days in current century after today -:param tzinfo: timezone, instance of datetime.tzinfo subclass -Example: DateTime('2012-04-04 11:02:02') -:return DateTime - -Aliases: date_time_this_century, datetimethiscentury - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/date_time/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.DateTimeThisCentury}} - block_example: - fake: DateTimeThisCentury - -Outputs: - - Example(id=1, inline_example=2016-07-13 21:34:49, block_example=2013-10-11 08:18:38) - -#### fake: DateTimeThisDecade - -Gets a DateTime object for the decade year. - -:param before_now: include days in current decade before today -:param after_now: include days in current decade after today -:param tzinfo: timezone, instance of datetime.tzinfo subclass -Example: DateTime('2012-04-04 11:02:02') -:return DateTime - -Aliases: date_time_this_decade, datetimethisdecade - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/date_time/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.DateTimeThisDecade}} - block_example: - fake: DateTimeThisDecade - -Outputs: - - Example(id=1, inline_example=2021-01-12 10:20:55, block_example=2020-11-10 12:31:09) - -#### fake: DateTimeThisMonth - -Gets a DateTime object for the current month. - -:param before_now: include days in current month before today -:param after_now: include days in current month after today -:param tzinfo: timezone, instance of datetime.tzinfo subclass -Example: DateTime('2012-04-04 11:02:02') -:return DateTime - -Aliases: date_time_this_month, datetimethismonth - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/date_time/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.DateTimeThisMonth}} - block_example: - fake: DateTimeThisMonth - -Outputs: - - Example(id=1, inline_example=2021-06-12 19:04:24, block_example=2021-06-10 19:53:28) - -#### fake: DateTimeThisYear - -Gets a DateTime object for the current year. - -:param before_now: include days in current year before today -:param after_now: include days in current year after today -:param tzinfo: timezone, instance of datetime.tzinfo subclass -Example: DateTime('2012-04-04 11:02:02') -:return DateTime - -Aliases: date_time_this_year, datetimethisyear - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/date_time/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.DateTimeThisYear}} - block_example: - fake: DateTimeThisYear - -Outputs: - - Example(id=1, inline_example=2021-04-10 06:42:46, block_example=2021-04-05 08:35:13) - -#### fake: DayOfMonth - -Aliases: day_of_month, dayofmonth - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/date_time/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.DayOfMonth}} - block_example: - fake: DayOfMonth - -Outputs: - - Example(id=1, inline_example=25, block_example=22) - -#### fake: DayOfWeek - -Aliases: day_of_week, dayofweek - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/date_time/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.DayOfWeek}} - block_example: - fake: DayOfWeek - -Outputs: - - Example(id=1, inline_example=Saturday, block_example=Tuesday) - -#### fake: FutureDate - -Get a Date object based on a random date between 1 day from now and a -given date. -Accepts date strings that can be recognized by strtotime(). - -:param end_date Defaults to "+30d" -:param tzinfo: timezone, instance of datetime.tzinfo subclass -Example: DateTime('1999-02-02 11:42:52') -:return DateTime - -Aliases: future_date, futuredate - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/date_time/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.FutureDate}} - block_example: - fake: FutureDate - -Outputs: - - Example(id=1, inline_example=2021-07-07, block_example=2021-07-03) - -#### fake: FutureDatetime - -Get a DateTime object based on a random date between 1 second form now -and a given date. -Accepts date strings that can be recognized by strtotime(). - -:param end_date Defaults to "+30d" -:param tzinfo: timezone, instance of datetime.tzinfo subclass -Example: DateTime('1999-02-02 11:42:52') -:return DateTime - -Aliases: future_datetime, futuredatetime - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/date_time/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.FutureDatetime}} - block_example: - fake: FutureDatetime - -Outputs: - - Example(id=1, inline_example=2021-07-07 04:14:42, block_example=2021-07-03 05:52:50) - -#### fake: Iso8601 - -:param tzinfo: timezone, instance of datetime.tzinfo subclass -Example: '2003-10-21T16:05:52+0000' - -Aliases: iso8601 - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/date_time/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.Iso8601}} - block_example: - fake: Iso8601 - -Outputs: - - Example(id=1, inline_example=2003-01-25T19:09:38, block_example=1997-07-22T16:37:16) - -#### fake: Month - -Aliases: month - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/date_time/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.Month}} - block_example: - fake: Month - -Outputs: - - Example(id=1, inline_example=1, block_example=07) - -#### fake: MonthName - -Aliases: month_name, monthname - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/date_time/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.MonthName}} - block_example: - fake: MonthName - -Outputs: - - Example(id=1, inline_example=January, block_example=July) - -#### fake: PastDate - -Get a Date object based on a random date between a given date and 1 day -ago. -Accepts date strings that can be recognized by strtotime(). - -:param start_date Defaults to "-30d" -:param tzinfo: timezone, instance of datetime.tzinfo subclass -Example: DateTime('1999-02-02 11:42:52') -:return DateTime - -Aliases: past_date, pastdate - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/date_time/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.PastDate}} - block_example: - fake: PastDate - -Outputs: - - Example(id=1, inline_example=2021-06-06, block_example=2021-06-02) - -#### fake: PastDatetime - -Get a DateTime object based on a random date between a given date and 1 -second ago. -Accepts date strings that can be recognized by strtotime(). - -:param start_date Defaults to "-30d" -:param tzinfo: timezone, instance of datetime.tzinfo subclass -Example: DateTime('1999-02-02 11:42:52') -:return DateTime - -Aliases: past_datetime, pastdatetime - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/date_time/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.PastDatetime}} - block_example: - fake: PastDatetime - -Outputs: - - Example(id=1, inline_example=2021-06-07 04:14:41, block_example=2021-06-03 05:52:49) - -#### fake: Pytimezone - -Generate a random timezone (see `faker.timezone` for any args) -and return as a python object usable as a `tzinfo` to `datetime` -or other fakers. - -Example: faker.pytimezone() -:return dateutil.tz.tz.tzfile - -Aliases: pytimezone - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/date_time/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.Pytimezone}} - block_example: - fake: Pytimezone - -Outputs: - - Example(id=1, inline_example=tzfile('/usr/share/zoneinfo/Pacific/Funafuti'), block_example=tzfile('/usr/share/zoneinfo/Africa/Khartoum')) - -#### fake: TimeDelta - -Get a timedelta object - -Aliases: time_delta, timedelta - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/date_time/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.TimeDelta}} - block_example: - fake: TimeDelta - -Outputs: - - Example(id=1, inline_example=0:00:00, block_example=0:00:00) - -#### fake: TimeObject - -Get a time object -Example: datetime.time(15, 56, 56, 772876) - -Aliases: time_object, timeobject - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/date_time/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.TimeObject}} - block_example: - fake: TimeObject - -Outputs: - - Example(id=1, inline_example=19:09:38, block_example=16:37:16) - -#### fake: TimeSeries - -Returns a generator yielding tuples of ``(, )``. - -The data points will start at ``start_date``, and be at every time interval specified by -``precision``. -``distrib`` is a callable that accepts ```` and returns ```` - -Aliases: time_series, timeseries - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/date_time/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.TimeSeries}} - block_example: - fake: TimeSeries - -Outputs: - - Example(id=1, inline_example=, block_example=) - -#### fake: Timezone - -Aliases: timezone - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/date_time/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.Timezone}} - block_example: - fake: Timezone - -Outputs: - - Example(id=1, inline_example=Pacific/Funafuti, block_example=Africa/Khartoum) - -#### fake: UnixTime - -Get a timestamp between January 1, 1970 and now, unless passed -explicit start_datetime or end_datetime values. -Example: 1061306726 - -Aliases: unix_time, unixtime - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/date_time/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.UnixTime}} - block_example: - fake: UnixTime - -Outputs: - - Example(id=1, inline_example=1043521778, block_example=869589436) - -### Decorators.Py Fakers - -#### fake: AsciiCompanyEmail - -Aliases: ascii_company_email, asciicompanyemail - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/utils/decorators.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.AsciiCompanyEmail}} - block_example: - fake: AsciiCompanyEmail - -Outputs: - - Example(id=1, inline_example=buckcourtney@tapia.com, block_example=vcrane@moon.com) - -#### fake: AsciiEmail - -Aliases: ascii_email, asciiemail - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/utils/decorators.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.AsciiEmail}} - block_example: - fake: AsciiEmail - -Outputs: - - Example(id=1, inline_example=yodonnell@wiggins.info, block_example=alishawhitehead@gmail.com) - -#### fake: AsciiFreeEmail - -Aliases: ascii_free_email, asciifreeemail - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/utils/decorators.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.AsciiFreeEmail}} - block_example: - fake: AsciiFreeEmail - -Outputs: - - Example(id=1, inline_example=edgar15@yahoo.com, block_example=lovefrances@yahoo.com) - -#### fake: AsciiSafeEmail - -Aliases: ascii_safe_email, asciisafeemail - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/utils/decorators.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.AsciiSafeEmail}} - block_example: - fake: AsciiSafeEmail - -Outputs: - - Example(id=1, inline_example=edgar15@example.com, block_example=lovefrances@example.com) - -#### fake: CompanyEmail - -Aliases: company_email, companyemail - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/utils/decorators.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.CompanyEmail}} - block_example: - fake: CompanyEmail - -Outputs: - - Example(id=1, inline_example=buckcourtney@tapia.com, block_example=vcrane@moon.com) - -#### fake: DomainName - -Produce an Internet domain name with the specified number of -subdomain levels. - ->>> domain_name() -nichols-phillips.com ->>> domain_name(2) -williamson-hopkins.jackson.com - -Aliases: domain_name, domainname - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/utils/decorators.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.DomainName}} - block_example: - fake: DomainName - -Outputs: - - Example(id=1, inline_example=vega.com, block_example=lyons.com) - -#### fake: DomainWord - -Aliases: domain_word, domainword - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/utils/decorators.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.DomainWord}} - block_example: - fake: DomainWord - -Outputs: - - Example(id=1, inline_example=krause-wilcox, block_example=bautista) - -#### fake: FreeEmail - -Aliases: free_email, freeemail - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/utils/decorators.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.FreeEmail}} - block_example: - fake: FreeEmail - -Outputs: - - Example(id=1, inline_example=edgar15@yahoo.com, block_example=lovefrances@yahoo.com) - -#### fake: FreeEmailDomain - -Aliases: free_email_domain, freeemaildomain - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/utils/decorators.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.FreeEmailDomain}} - block_example: - fake: FreeEmailDomain - -Outputs: - - Example(id=1, inline_example=yahoo.com, block_example=yahoo.com) - -#### fake: Hostname - -Produce a hostname with specified number of subdomain levels. - ->>> hostname() -db-01.nichols-phillips.com ->>> hostname(0) -laptop-56 ->>> hostname(2) -web-12.williamson-hopkins.jackson.com - -Aliases: hostname - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/utils/decorators.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.Hostname}} - block_example: - fake: Hostname - -Outputs: - - Example(id=1, inline_example=lt-77.fowler.net, block_example=db-16.tapia.com) - -#### fake: SafeDomainName - -Aliases: safe_domain_name, safedomainname - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/utils/decorators.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.SafeDomainName}} - block_example: - fake: SafeDomainName - -Outputs: - - Example(id=1, inline_example=example.com, block_example=example.com) - -#### fake: SafeEmail - -Aliases: safe_email, safeemail - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/utils/decorators.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.SafeEmail}} - block_example: - fake: SafeEmail - -Outputs: - - Example(id=1, inline_example=edgar15@example.com, block_example=lovefrances@example.com) - -#### fake: Slug - -Django algorithm - -Aliases: slug - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/utils/decorators.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.Slug}} - block_example: - fake: Slug - -Outputs: - - Example(id=1, inline_example=discover-mother, block_example=father-challenge) - -### File Fakers - -#### fake: FileExtension - -Generate a file extension under the specified ``category``. - -If ``category`` is ``None``, a random category will be used. The list of -valid categories include: ``'audio'``, ``'image'``, ``'office'``, -``'text'``, and ``'video'``. - -Aliases: file_extension, fileextension - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/file/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.FileExtension}} - block_example: - fake: FileExtension - -Outputs: - - Example(id=1, inline_example=js, block_example=ods) - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.FileExtension(category='image')}} - block_example: - fake.FileExtension: - category: image - -Outputs: - - Example(id=1, inline_example=jpeg, block_example=png) - -#### fake: FileName - -Generate a random file name with extension. - -If ``extension`` is ``None``, a random extension will be created under -the hood using |file_extension| with the specified ``category``. If a -value for ``extension`` is provided, the value will be used instead, -and ``category`` will be ignored. The actual name part itself is -generated using |word|. - -:sample size=10: - -Aliases: file_name, filename - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/file/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.FileName}} - block_example: - fake: FileName - -Outputs: - - Example(id=1, inline_example=much.mp3, block_example=why.js) - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.FileName(category='audio')}} - block_example: - fake.FileName: - category: audio - -Outputs: - - Example(id=1, inline_example=me.mp3, block_example=past.mp3) - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.FileName(extension='abcdef')}} - block_example: - fake.FileName: - extension: abcdef - -Outputs: - - Example(id=1, inline_example=wait.abcdef, block_example=whatever.abcdef) - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.FileName(category='audio', extension='abcdef')}} - block_example: - fake.FileName: - category: audio - extension: abcdef - -Outputs: - - Example(id=1, inline_example=discover.abcdef, block_example=mother.abcdef) - -#### fake: FilePath - -Generate an absolute pathname to a file. - -This method uses |file_name| under the hood to generate the file name -itself, and ``depth`` controls the depth of the directory path, and -|word| is used under the hood to generate the different directory names. - -:sample size=10: - -Aliases: file_path, filepath - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/file/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.FilePath}} - block_example: - fake: FilePath - -Outputs: - - Example(id=1, inline_example=/bit/force.avi, block_example=/marriage/give.wav) - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.FilePath(depth=3)}} - block_example: - fake.FilePath: - depth: 3 - -Outputs: - - Example(id=1, inline_example=/popular/four/leader/health.mp4, block_example=/near/tree/level/me.png) - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.FilePath(depth=5, category='video')}} - block_example: - fake.FilePath: - depth: 5 - category: video - -Outputs: - - Example(id=1, inline_example=/address/whole/official/why/support/assume.mov, block_example=/still/thank/see/inside/though/serve.mp4) - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.FilePath(depth=5, category='video', extension='abcdef')}} - block_example: - fake.FilePath: - depth: 5 - category: video - extension: abcdef - -Outputs: - - Example(id=1, inline_example=/their/minute/population/ability/process/relate.abcdef, block_example=/score/gas/show/either/goal/trip.abcdef) - -#### fake: MimeType - -Generate a mime type under the specified ``category``. - -If ``category`` is ``None``, a random category will be used. The list of -valid categories include ``'application'``, ``'audio'``, ``'image'``, -``'message'``, ``'model'``, ``'multipart'``, ``'text'``, and -``'video'``. - -Aliases: mime_type, mimetype - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/file/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.MimeType}} - block_example: - fake: MimeType - -Outputs: - - Example(id=1, inline_example=video/x-ms-wmv, block_example=model/vrml) - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.MimeType(category='application')}} - block_example: - fake.MimeType: - category: application - -Outputs: - - Example(id=1, inline_example=application/rss+xml, block_example=application/gzip) - -#### fake: UnixDevice - -Generate a Unix device file name. - -If ``prefix`` is ``None``, a random prefix will be used. The list of -valid prefixes include: ``'sd'``, ``'vd'``, and ``'xvd'``. - -Aliases: unix_device, unixdevice - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/file/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.UnixDevice}} - block_example: - fake: UnixDevice - -Outputs: - - Example(id=1, inline_example=/dev/xvdp, block_example=/dev/vdz) - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.UnixDevice(prefix='mmcblk')}} - block_example: - fake.UnixDevice: - prefix: mmcblk - -Outputs: - - Example(id=1, inline_example=/dev/mmcblkj, block_example=/dev/mmcblkp) - -#### fake: UnixPartition - -Generate a Unix partition name. - -This method uses |unix_device| under the hood to create a device file -name with the specified ``prefix``. - -Aliases: unix_partition, unixpartition - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/file/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.UnixPartition}} - block_example: - fake: UnixPartition - -Outputs: - - Example(id=1, inline_example=/dev/xvdg8, block_example=/dev/sdj2) - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.UnixPartition(prefix='mmcblk')}} - block_example: - fake.UnixPartition: - prefix: mmcblk - -Outputs: - - Example(id=1, inline_example=/dev/mmcblky1, block_example=/dev/mmcblkt4) - -### Geo Fakers - -#### fake: Coordinate - -Optionally center the coord and pick a point within radius. - -Aliases: coordinate - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/geo/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.Coordinate}} - block_example: - fake: Coordinate - -Outputs: - - Example(id=1, inline_example=80.880444, block_example=37.397359) - -#### fake: Latitude - -Aliases: latitude - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/geo/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.Latitude}} - block_example: - fake: Latitude - -Outputs: - - Example(id=1, inline_example=40.440222, block_example=18.6986795) - -#### fake: Latlng - -Aliases: latlng - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/geo/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.Latlng}} - block_example: - fake: Latlng - -Outputs: - - Example(id=1, inline_example=(Decimal('66.6004235'), Decimal('-62.724453')), block_example=(Decimal('45.475847'), Decimal('-105.227997'))) - -#### fake: LocalLatlng - -Returns a location known to exist on land in a country specified by `country_code`. -Defaults to 'en_US'. See the `land_coords` list for available locations/countries. - -Aliases: local_latlng, locallatlng - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/geo/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.LocalLatlng}} - block_example: - fake: LocalLatlng - -Outputs: - - Example(id=1, inline_example=('33.03699', '-117.29198', 'Encinitas', 'US', 'America/Los_Angeles'), block_example=('41.0051', '-73.78458', 'Scarsdale', 'US', 'America/New_York')) - -#### fake: LocationOnLand - -Returns a random tuple specifying a coordinate set guaranteed to exist on land. -Format is `(latitude, longitude, place name, two-letter country code, timezone)` -Pass `coords_only` to return coordinates without metadata. - -Aliases: location_on_land, locationonland - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/geo/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.LocationOnLand}} - block_example: - fake: LocationOnLand - -Outputs: - - Example(id=1, inline_example=('43.4125', '23.225', 'Montana', 'BG', 'Europe/Sofia'), block_example=('65.84811', '24.14662', 'Tornio', 'FI', 'Europe/Helsinki')) - -#### fake: Longitude - -Aliases: longitude - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/geo/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.Longitude}} - block_example: - fake: Longitude - -Outputs: - - Example(id=1, inline_example=80.880444, block_example=37.397359) - -### Internet Fakers - -#### fake: Dga - -Generates a domain name by given date -https://en.wikipedia.org/wiki/Domain_generation_algorithm - -:type year: int -:type month: int -:type day: int -:type tld: str -:type length: int -:rtype: str - -Aliases: dga - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/internet/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.Dga}} - block_example: - fake: Dga - -Outputs: - - Example(id=1, inline_example=rirpbubretascqucvnrhbyydewtmalpjievdbixsxknwnwelialvretierm.com, block_example=fctbfriciqlcbvrqhfsxrotu.com) - -#### fake: HttpMethod - -Returns random HTTP method -https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods - -:rtype: str - -Aliases: http_method, httpmethod - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/internet/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.HttpMethod}} - block_example: - fake: HttpMethod - -Outputs: - - Example(id=1, inline_example=TRACE, block_example=OPTIONS) - -#### fake: ImageUrl - -Returns URL to placeholder image -Example: http://placehold.it/640x480 - -Aliases: image_url, imageurl - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/internet/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.ImageUrl}} - block_example: - fake: ImageUrl - -Outputs: - - Example(id=1, inline_example=https://www.lorempixel.com/300/635, block_example=https://placeimg.com/151/676/any) - -#### fake: Ipv4 - -Returns a random IPv4 address or network with a valid CIDR. - -:param network: Network address -:param address_class: IPv4 address class (a, b, or c) -:param private: Public or private -:returns: IPv4 - -Aliases: ipv4 - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/internet/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.Ipv4}} - block_example: - fake: Ipv4 - -Outputs: - - Example(id=1, inline_example=12.130.104.103, block_example=70.17.181.9) - -#### fake: Ipv4NetworkClass - -Returns a IPv4 network class 'a', 'b' or 'c'. - -:returns: IPv4 network class - -Aliases: ipv4_network_class, ipv4networkclass - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/internet/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.Ipv4NetworkClass}} - block_example: - fake: Ipv4NetworkClass - -Outputs: - - Example(id=1, inline_example=b, block_example=b) - -#### fake: Ipv4Private - -Returns a private IPv4. - -:param network: Network address -:param address_class: IPv4 address class (a, b, or c) -:returns: Private IPv4 - -Aliases: ipv4_private, ipv4private - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/internet/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.Ipv4Private}} - block_example: - fake: Ipv4Private - -Outputs: - - Example(id=1, inline_example=10.128.66.93, block_example=192.168.75.62) - -#### fake: Ipv4Public - -Returns a public IPv4 excluding private blocks. - -:param network: Network address -:param address_class: IPv4 address class (a, b, or c) -:returns: Public IPv4 - -Aliases: ipv4_public, ipv4public - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/internet/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.Ipv4Public}} - block_example: - fake: Ipv4Public - -Outputs: - - Example(id=1, inline_example=48.8.75.189, block_example=198.165.159.67) - -#### fake: Ipv6 - -Produce a random IPv6 address or network with a valid CIDR - -Aliases: ipv6 - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/internet/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.Ipv6}} - block_example: - fake: Ipv6 - -Outputs: - - Example(id=1, inline_example=23a7:711a:8133:2876:37eb:dcda:e87a:1613, block_example=1846:d424:c17c:6279:23c6:6130:4826:8673) - -#### fake: MacAddress - -Aliases: mac_address, macaddress - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/internet/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.MacAddress}} - block_example: - fake: MacAddress - -Outputs: - - Example(id=1, inline_example=07:2f:cc:00:fc:aa, block_example=7c:a6:20:61:71:7a) - -#### fake: PortNumber - -Returns a network port number -https://tools.ietf.org/html/rfc6335 - -:param is_system: System or well-known ports -:param is_user: User or registered ports -:param is_dynamic: Dynamic / private / ephemeral ports -:rtype: int - -Aliases: port_number, portnumber - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/internet/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.PortNumber}} - block_example: - fake: PortNumber - -Outputs: - - Example(id=1, inline_example=53075, block_example=39755) - -#### fake: Tld - -Aliases: tld - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/internet/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.Tld}} - block_example: - fake: Tld - -Outputs: - - Example(id=1, inline_example=info, block_example=biz) - -#### fake: Uri - -Aliases: uri - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/internet/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.Uri}} - block_example: - fake: Uri - -Outputs: - - Example(id=1, inline_example=http://www.harding.info/home/, block_example=https://lowe.com/) - -#### fake: UriExtension - -Aliases: uri_extension, uriextension - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/internet/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.UriExtension}} - block_example: - fake: UriExtension - -Outputs: - - Example(id=1, inline_example=.jsp, block_example=.php) - -#### fake: UriPage - -Aliases: uri_page, uripage - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/internet/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.UriPage}} - block_example: - fake: UriPage - -Outputs: - - Example(id=1, inline_example=post, block_example=login) - -#### fake: UriPath - -Aliases: uri_path, uripath - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/internet/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.UriPath}} - block_example: - fake: UriPath - -Outputs: - - Example(id=1, inline_example=main, block_example=posts/explore/categories) - -#### fake: Url - -:param schemes: a list of strings to use as schemes, one will chosen randomly. -If None, it will generate http and https urls. -Passing an empty list will result in schemeless url generation like "://domain.com". - -:returns: a random url string. - -Aliases: url - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/internet/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.Url}} - block_example: - fake: Url - -Outputs: - - Example(id=1, inline_example=https://fowler.net/, block_example=http://www.huber.com/) - -### Isbn Fakers - -#### fake: Isbn10 - -Aliases: isbn10 - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/isbn/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.Isbn10}} - block_example: - fake: Isbn10 - -Outputs: - - Example(id=1, inline_example=1-115-87148-X, block_example=0-85839-894-X) - -#### fake: Isbn13 - -Aliases: isbn13 - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/isbn/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.Isbn13}} - block_example: - fake: Isbn13 - -Outputs: - - Example(id=1, inline_example=978-1-115-87148-8, block_example=978-0-85839-894-8) - -### Job Fakers - -#### fake: Job - -Aliases: job - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/job/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.Job}} - block_example: - fake: Job - -Outputs: - - Example(id=1, inline_example=Radiographer, diagnostic, block_example=Ophthalmologist) - -### Lorem Fakers - -#### fake: Paragraphs - -Generate a list of paragraphs. - -This method uses |paragraph| under the hood to generate paragraphs, and -the ``nb`` argument controls exactly how many sentences the list will -contain. The ``ext_word_list`` argument works in exactly the same way -as well. - -Aliases: paragraphs - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/lorem/__init__.py) - -#### fake: Sentences - -Generate a list of sentences. - -This method uses |sentence| under the hood to generate sentences, and -the ``nb`` argument controls exactly how many sentences the list will -contain. The ``ext_word_list`` argument works in exactly the same way -as well. - -Aliases: sentences - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/lorem/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.Sentences}} - block_example: - fake: Sentences - -Outputs: - - Example(id=1, inline_example=['Bring TV program actually race.', 'Themselves true power home price check real.', 'Score from animal exactly drive well good.'], block_example=['Pull opportunity throughout take car.', 'Hold increase practice ability court.', 'Civil development large report purpose themselves.']) - -#### fake: Texts - -Generate a list of text strings. - -The ``nb_texts`` argument controls how many text strings the list will -contain, and this method uses |text| under the hood for text generation, -so the two remaining arguments, ``max_nb_chars`` and ``ext_word_list`` -will work in exactly the same way as well. - - - -ext_word_list=['abc', 'def', 'ghi', 'jkl'] - -Aliases: texts - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/lorem/__init__.py) - -#### fake: Words - -Generate a tuple of words. - -The ``nb`` argument controls the number of words in the resulting list, -and if ``ext_word_list`` is provided, words from that list will be used -instead of those from the locale provider's built-in word list. - -If ``unique`` is ``True``, this method will return a list containing -unique words. Under the hood, |random_sample| will be used for sampling -without replacement. If ``unique`` is ``False``, |random_choices| is -used instead, and the list returned may contain duplicates. - -.. warning:: -Depending on the length of a locale provider's built-in word list or -on the length of ``ext_word_list`` if provided, a large ``nb`` can -exhaust said lists if ``unique`` is ``True``, raising an exception. - -Aliases: words - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/lorem/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.Words}} - block_example: - fake: Words - -Outputs: - - Example(id=1, inline_example=['together', 'range', 'line'], block_example=['beyond', 'its', 'particularly']) - -### Misc Fakers - -#### fake: Binary - -Generate a random binary blob of ``length`` bytes. - -Aliases: binary - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/misc/__init__.py) - -#### fake: Boolean - -Generate a random boolean value based on ``chance_of_getting_true``. - -:sample size=10: chance_of_getting_true=25 -:sample size=10: chance_of_getting_true=50 -:sample size=10: chance_of_getting_true=75 - -Aliases: boolean - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/misc/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.Boolean(chance_of_getting_true=25)}} - block_example: - fake.Boolean: - chance_of_getting_true: 25 - -Outputs: - - Example(id=1, inline_example=False, block_example=0) - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.Boolean(chance_of_getting_true=50)}} - block_example: - fake.Boolean: - chance_of_getting_true: 50 - -Outputs: - - Example(id=1, inline_example=True, block_example=0) - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.Boolean(chance_of_getting_true=75)}} - block_example: - fake.Boolean: - chance_of_getting_true: 75 - -Outputs: - - Example(id=1, inline_example=True, block_example=1) - -#### fake: Csv - -Generate random comma-separated values. - -For more information on the different arguments of this method, please refer to -:meth:`dsv() ` which is used under the hood. - - -data_columns=('{{name}}', '{{address}}', '{{safe_color_name}}'), -num_rows=10, include_row_ids=True - -Aliases: csv - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/misc/__init__.py) - -#### fake: Dsv - -Generate random delimiter-separated values. - -This method's behavior share some similarities with ``csv.writer``. The ``dialect`` and -``**fmtparams`` arguments are the same arguments expected by ``csv.writer`` to control its -behavior, and instead of expecting a file-like object to where output will be written, the -output is controlled by additional keyword arguments and is returned as a string. - -The ``dialect`` argument defaults to ``'faker-csv'`` which is the name of a ``csv.excel`` -subclass with full quoting enabled. - -The ``header`` argument expects a list or a tuple of strings that will serve as the header row -if supplied. The ``data_columns`` argument expects a list or a tuple of string tokens, and these -string tokens will be passed to :meth:`pystr_format() ` -for data generation. Argument Groups are used to pass arguments to the provider methods. -Both ``header`` and ``data_columns`` must be of the same length. - -Example: -fake.set_arguments('top_half', {'min_value': 50, 'max_value': 100}) -fake.dsv(data_columns=('{{ name }}', '{{ pyint:top_half }}')) - -The ``num_rows`` argument controls how many rows of data to generate, and the ``include_row_ids`` -argument may be set to ``True`` to include a sequential row ID column. - -Aliases: dsv - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/misc/__init__.py) - -#### fake: FixedWidth - -Generate random fixed width values. - -Using a list of tuple records that is passed as ``data_columns``, that -defines the structure that will be generated. Arguments within the -record are provider specific, and should be a dictionary that will be -passed to the provider method. - -Data Column List format -[('field width', 'definition', {'arguments'})] - -The definition can be 'provider', 'provider:argument_group', tokenized -'string {{ provider:argument_group }}' that is passed to the python -provider method pystr_format() for generation, or a fixed '@word'. -Using Lists, Tuples, and Dicts as a definition for structure. - -Argument Groups can be used to pass arguments to the provider methods, -but will override the arguments supplied in the tuple record. - -Example: -fake.set_arguments('top_half', {'min_value': 50, 'max_value': 100}) -fake.fixed_width(data_columns=[(20, 'name'), (3, 'pyint:top_half')]) - -:param data_columns: specification for the data structure -:type data_columns: list -:param num_rows: number of rows the generator will yield -:type num_rows: int -:param align: positioning of the value. (left, middle, right) -:type align: str -:return: Serialized Fixed Width data -:rtype: str - -'max_value': 100})], align='right', num_rows=2 - -Aliases: fixed_width, fixedwidth - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/misc/__init__.py) - -#### fake: Json - -Generate random JSON structure values. - -Using a dictionary or list of records that is passed as ``data_columns``, -define the structure that is used to build JSON structures. For complex -data structures it is recommended to use the dictionary format. - -Data Column Dictionary format: -{'key name': 'definition'} - -The definition can be 'provider', 'provider:argument_group', tokenized -'string {{ provider:argument_group }}' that is passed to the python -provider method pystr_format() for generation, or a fixed '@word'. -Using Lists, Tuples, and Dicts as a definition for structure. - -Example: -fake.set_arguments('top_half', {'min_value': 50, 'max_value': 100}) -fake.json(data_columns={'Name': 'name', 'Score': 'pyint:top_half'}) - -Data Column List format: -[('key name', 'definition', {'arguments'})] - -With the list format the definition can be a list of records, to create -a list within the structure data. For literal entries within the list, -set the 'field_name' to None. - -:param data_columns: specification for the data structure -:type data_columns: dict -:param num_rows: number of rows the returned -:type num_rows: int -:param indent: number of spaces to indent the fields -:type indent: int -:return: Serialized JSON data -:rtype: str - -'Details': {'Name': 'name', 'Address': 'address'}}, num_rows=2 - -num_rows=1 - -{'min_value': 50, 'max_value': 100})], num_rows=1 - -Aliases: json - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/misc/__init__.py) - -#### fake: Md5 - -Generate a random MD5 hash. - -If ``raw_output`` is ``False`` (default), a hexadecimal string representation of the MD5 hash -will be returned. If ``True``, a ``bytes`` object representation will be returned instead. - -Aliases: md5 - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/misc/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.Md5(raw_output=False)}} - block_example: - fake.Md5: - raw_output: false - -Outputs: - - Example(id=1, inline_example=0ced544422ae9d74b425752334506cb5, block_example=e2e862d8792e2235570eb2eb93f0b720) - -#### fake: NullBoolean - -Generate ``None``, ``True``, or ``False``, each with equal probability. - -:sample size=15: - -Aliases: null_boolean, nullboolean - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/misc/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.NullBoolean}} - block_example: - fake: NullBoolean - -Outputs: - - Example(id=1, inline_example=False, block_example=False) - -#### fake: Password - -Generate a random password of the specified ``length``. - -The arguments ``special_chars``, ``digits``, ``upper_case``, and ``lower_case`` control -what category of characters will appear in the generated password. If set to ``True`` -(default), at least one character from the corresponding category is guaranteed to appear. -Special characters are characters from ``!@#$%^&*()_+``, digits are characters from -``0123456789``, and uppercase and lowercase characters are characters from the ASCII set of -letters. - -Aliases: password - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/misc/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.Password(length=12)}} - block_example: - fake.Password: - length: 12 - -Outputs: - - Example(id=1, inline_example=z(1Bef!mR*(X, block_example=@tlUcamZ*+6$) - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.Password(length=40, special_chars=False, upper_case=False)}} - block_example: - fake.Password: - length: 40 - special_chars: false - upper_case: false - -Outputs: - - Example(id=1, inline_example=xw1qpnplndj7l05cspcm15zaejah816i2ebe3whu, block_example=pfaqwxddz723q20eighlofdz9rfc2vpwgo4e71y7) - -#### fake: Psv - -Generate random pipe-separated values. - -For more information on the different arguments of this method, please refer to -:meth:`dsv() ` which is used under the hood. - - -data_columns=('{{name}}', '{{address}}', '{{safe_color_name}}'), -num_rows=10, include_row_ids=True - -Aliases: psv - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/misc/__init__.py) - -#### fake: Sha1 - -Generate a random SHA1 hash. - -If ``raw_output`` is ``False`` (default), a hexadecimal string representation of the SHA1 hash -will be returned. If ``True``, a ``bytes`` object representation will be returned instead. - -Aliases: sha1 - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/misc/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.Sha1(raw_output=False)}} - block_example: - fake.Sha1: - raw_output: false - -Outputs: - - Example(id=1, inline_example=c6b69eb0fa28e2085eee479bb87f7bdfcee2e3b4, block_example=f57a6cb25f89722d7389101a0ef9f9547930c529) - -#### fake: Sha256 - -Generate a random SHA256 hash. - -If ``raw_output`` is ``False`` (default), a hexadecimal string representation of the SHA56 hash -will be returned. If ``True``, a ``bytes`` object representation will be returned instead. - -Aliases: sha256 - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/misc/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.Sha256(raw_output=False)}} - block_example: - fake.Sha256: - raw_output: false - -Outputs: - - Example(id=1, inline_example=faa5be1206846743dec0c4d3e5afc2d48a023011fdb6eabcc842f2b47eca8a00, block_example=8e36506d1af0f8133ec6c833feb77689049fec2a0f7a49b8218fd49f41fde9d9) - -#### fake: Tar - -Generate a bytes object containing a random valid tar file. - -The number and sizes of files contained inside the resulting archive can be controlled -using the following arguments: - -- ``uncompressed_size`` - the total size of files before compression, 16 KiB by default -- ``num_files`` - the number of files archived in resulting zip file, 1 by default -- ``min_file_size`` - the minimum size of each file before compression, 4 KiB by default - -No compression is used by default, but setting ``compression`` to one of the values listed -below will use the corresponding compression type. - -- ``'bzip2'`` or ``'bz2'`` for BZIP2 -- ``'lzma'`` or ``'xz'`` for LZMA -- ``'gzip'`` or ``'gz'`` for GZIP - -Aliases: tar - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/misc/__init__.py) - -#### fake: Tsv - -Generate random tab-separated values. - -For more information on the different arguments of this method, please refer to -:meth:`dsv() ` which is used under the hood. - - -data_columns=('{{name}}', '{{address}}', '{{safe_color_name}}'), -num_rows=10, include_row_ids=True - -Aliases: tsv - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/misc/__init__.py) - -#### fake: Uuid4 - -Generate a random UUID4 object and cast it to another type if specified using a callable ``cast_to``. - -By default, ``cast_to`` is set to ``str``. - -May be called with ``cast_to=None`` to return a full-fledged ``UUID``. - -Aliases: uuid4 - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/misc/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.Uuid4}} - block_example: - fake: Uuid4 - -Outputs: - - Example(id=1, inline_example=23a7711a-8133-4876-b7eb-dcd9e87a1613, block_example=1846d424-c17c-4279-a3c6-612f48268673) - -#### fake: Zip - -Generate a bytes object containing a random valid zip archive file. - -The number and sizes of files contained inside the resulting archive can be controlled -using the following arguments: - -- ``uncompressed_size`` - the total size of files before compression, 16 KiB by default -- ``num_files`` - the number of files archived in resulting zip file, 1 by default -- ``min_file_size`` - the minimum size of each file before compression, 4 KiB by default - -No compression is used by default, but setting ``compression`` to one of the values listed -below will use the corresponding compression type. - -- ``'bzip2'`` or ``'bz2'`` for BZIP2 -- ``'lzma'`` or ``'xz'`` for LZMA -- ``'deflate'``, ``'gzip'``, or ``'gz'`` for GZIP - -Aliases: zip - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/misc/__init__.py) - -### Person Fakers - -#### fake: LanguageName - -Generate a random i18n language name (e.g. English). - -Aliases: language_name, languagename - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/person/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.LanguageName}} - block_example: - fake: LanguageName - -Outputs: - - Example(id=1, inline_example=Ossetian, block_example=Macedonian) - -#### fake: LastNameFemale - -Aliases: last_name_female, lastnamefemale - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/person/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.LastNameFemale}} - block_example: - fake: LastNameFemale - -Outputs: - - Example(id=1, inline_example=Goodwin, block_example=Hendrix) - -#### fake: LastNameMale - -Aliases: last_name_male, lastnamemale - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/person/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.LastNameMale}} - block_example: - fake: LastNameMale - -Outputs: - - Example(id=1, inline_example=Goodwin, block_example=Hendrix) - -#### fake: LastNameNonbinary - -Aliases: last_name_nonbinary, lastnamenonbinary - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/person/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.LastNameNonbinary}} - block_example: - fake: LastNameNonbinary - -Outputs: - - Example(id=1, inline_example=Goodwin, block_example=Hendrix) - -#### fake: NameNonbinary - -Aliases: name_nonbinary, namenonbinary - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/person/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.NameNonbinary}} - block_example: - fake: NameNonbinary - -Outputs: - - Example(id=1, inline_example=Lydia Escobar III, block_example=Edgar Moon II) - -#### fake: Prefix - -Aliases: prefix - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/person/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.Prefix}} - block_example: - fake: Prefix - -Outputs: - - Example(id=1, inline_example=Mr., block_example=Ms.) - -#### fake: PrefixFemale - -Aliases: prefix_female, prefixfemale - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/person/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.PrefixFemale}} - block_example: - fake: PrefixFemale - -Outputs: - - Example(id=1, inline_example=Dr., block_example=Miss) - -#### fake: PrefixMale - -Aliases: prefix_male, prefixmale - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/person/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.PrefixMale}} - block_example: - fake: PrefixMale - -Outputs: - - Example(id=1, inline_example=Dr., block_example=Dr.) - -#### fake: PrefixNonbinary - -Aliases: prefix_nonbinary, prefixnonbinary - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/person/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.PrefixNonbinary}} - block_example: - fake: PrefixNonbinary - -Outputs: - - Example(id=1, inline_example=Dr., block_example=Misc.) - -#### fake: Suffix - -Aliases: suffix - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/person/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.Suffix}} - block_example: - fake: Suffix - -Outputs: - - Example(id=1, inline_example=DVM, block_example=V) - -#### fake: SuffixFemale - -Aliases: suffix_female, suffixfemale - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/person/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.SuffixFemale}} - block_example: - fake: SuffixFemale - -Outputs: - - Example(id=1, inline_example=DVM, block_example=PhD) - -#### fake: SuffixMale - -Aliases: suffix_male, suffixmale - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/person/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.SuffixMale}} - block_example: - fake: SuffixMale - -Outputs: - - Example(id=1, inline_example=DDS, block_example=V) - -#### fake: SuffixNonbinary - -Aliases: suffix_nonbinary, suffixnonbinary - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/person/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.SuffixNonbinary}} - block_example: - fake: SuffixNonbinary - -Outputs: - - Example(id=1, inline_example=DDS, block_example=V) - -### Phone_Number Fakers - -#### fake: CountryCallingCode - -Aliases: country_calling_code, countrycallingcode - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/phone_number/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.CountryCallingCode}} - block_example: - fake: CountryCallingCode - -Outputs: - - Example(id=1, inline_example=+386, block_example=+1 670) - -#### fake: Msisdn - -https://en.wikipedia.org/wiki/MSISDN - -Aliases: msisdn - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/phone_number/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.Msisdn}} - block_example: - fake: Msisdn - -Outputs: - - Example(id=1, inline_example=9894719659342, block_example=2094711220186) - -### Profile Fakers - -#### fake: Profile - -Generates a complete profile. -If "fields" is not empty, only the fields in the list will be returned - -Aliases: profile - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/profile/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.Profile}} - block_example: - fake: Profile - -Outputs: - - Example(id=1, inline_example={'job': 'Chartered loss adjuster', 'company': 'Landry Inc', 'ssn': '203-96-3622', 'residence': '16884 Mcgrath Overpass Apt. 615\nWest Paula, GA 57022', 'current_location': (Decimal('-38.4751525'), Decimal('12.479165')), 'blood_group': 'A-', 'website': ['http://johnston.biz/'], 'username': 'erikduncan', 'name': 'Mr. Eugene Pitts', 'sex': 'M', 'address': 'Unit 6582 Box 1972\nDPO AP 53704', 'mail': 'hnovak@yahoo.com', 'birthdate': datetime.date(1997, 11, 26)}, block_example={'job': 'IT trainer', 'company': 'Lamb-Walter', 'ssn': '687-26-8894', 'residence': 'PSC 0555, Box 0824\nAPO AP 20935', 'current_location': (Decimal('11.7384085'), Decimal('132.967921')), 'blood_group': 'AB+', 'website': ['http://www.church.com/', 'http://www.leonard.info/', 'https://www.church.info/', 'https://shepherd.com/'], 'username': 'yrubio', 'name': 'Ms. Jade Poole DVM', 'sex': 'F', 'address': 'Unit 9930 Box 0248\nDPO AP 33853', 'mail': 'curtis74@yahoo.com', 'birthdate': datetime.date(2010, 8, 1)}) - -#### fake: SimpleProfile - -Generates a basic profile with personal informations - -Aliases: simple_profile, simpleprofile - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/profile/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.SimpleProfile}} - block_example: - fake: SimpleProfile - -Outputs: - - Example(id=1, inline_example={'username': 'gkane', 'name': 'Tammie Harris', 'sex': 'F', 'address': 'USS George\nFPO AE 85294', 'mail': 'becky62@gmail.com', 'birthdate': datetime.date(1973, 12, 28)}, block_example={'username': 'qberry', 'name': 'Trevor Patterson', 'sex': 'M', 'address': 'USCGC Sosa\nFPO AP 22707', 'mail': 'colinhurley@hotmail.com', 'birthdate': datetime.date(1926, 12, 24)}) - -### Providers Fakers - -#### fake: Bothify - -Generate a string with each placeholder in ``text`` replaced according -to the following rules: - -- Number signs ('#') are replaced with a random digit (0 to 9). -- Question marks ('?') are replaced with a random character from ``letters``. - -By default, ``letters`` contains all ASCII letters, uppercase and lowercase. - -Under the hood, this method uses :meth:`numerify() ` and -and :meth:`lexify() ` to generate random values for number -signs and question marks respectively. - -Aliases: bothify - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.Bothify(letters='ABCDE')}} - block_example: - fake.Bothify: - letters: ABCDE - -Outputs: - - Example(id=1, inline_example=58 DA, block_example=48 CA) - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: '${{fake.Bothify(text=''Product Number: ????-########'')}}' - block_example: - fake.Bothify: - text: 'Product Number: ????-########' - -Outputs: - - Example(id=1, inline_example=Product Number: CfMZ-85839894, block_example=Product Number: cNQq-65934232) - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: '${{fake.Bothify(text=''Product Number: ????-########'', letters=''ABCDE'')}}' - block_example: - fake.Bothify: - text: 'Product Number: ????-########' - letters: ABCDE - -Outputs: - - Example(id=1, inline_example=Product Number: DECE-71122018, block_example=Product Number: CACE-33969477) - -#### fake: Hexify - -Generate a string with each circumflex ('^') in ``text`` -replaced with a random hexadecimal character. - -By default, ``upper`` is set to False. If set to ``True``, output -will be formatted using uppercase hexadecimal characters. - -Aliases: hexify - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: '${{fake.Hexify(text=''MAC Address: ^^:^^:^^:^^:^^:^^'')}}' - block_example: - fake.Hexify: - text: 'MAC Address: ^^:^^:^^:^^:^^:^^' - -Outputs: - - Example(id=1, inline_example=MAC Address: 95:65:18:f2:24:41, block_example=MAC Address: 2c:87:6d:8e:fb:2a) - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: '${{fake.Hexify(text=''MAC Address: ^^:^^:^^:^^:^^:^^'', upper=True)}}' - block_example: - fake.Hexify: - text: 'MAC Address: ^^:^^:^^:^^:^^:^^' - upper: true - -Outputs: - - Example(id=1, inline_example=MAC Address: 3F:A6:70:83:7B:5A, block_example=MAC Address: D1:34:71:20:36:3C) - -#### fake: LanguageCode - -Generate a random i18n language code (e.g. en). - -Aliases: language_code, languagecode - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.LanguageCode}} - block_example: - fake: LanguageCode - -Outputs: - - Example(id=1, inline_example=pap, block_example=mn) - -#### fake: Lexify - -Generate a string with each question mark ('?') in ``text`` -replaced with a random character from ``letters``. - -By default, ``letters`` contains all ASCII letters, uppercase and lowercase. - -Aliases: lexify - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: '${{fake.Lexify(text=''Random Identifier: ??????????'')}}' - block_example: - fake.Lexify: - text: 'Random Identifier: ??????????' - -Outputs: - - Example(id=1, inline_example=Random Identifier: TemKopZjZI, block_example=Random Identifier: CffuGFgtJs) - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: '${{fake.Lexify(text=''Random Identifier: ??????????'', letters=''ABCDE'')}}' - block_example: - fake.Lexify: - text: 'Random Identifier: ??????????' - letters: ABCDE - -Outputs: - - Example(id=1, inline_example=Random Identifier: AECEBEEECD, block_example=Random Identifier: AEDCEBCBBB) - -#### fake: Locale - -Generate a random underscored i18n locale code (e.g. en_US). - -Aliases: locale - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.Locale}} - block_example: - fake: Locale - -Outputs: - - Example(id=1, inline_example=sw_KE, block_example=raj_IN) - -#### fake: Numerify - -Generate a string with each placeholder in ``text`` replaced according -to the following rules: - -- Number signs ('#') are replaced with a random digit (0 to 9). -- Percent signs ('%') are replaced with a random non-zero digit (1 to 9). -- Exclamation marks ('!') are replaced with a random digit or an empty string. -- At symbols ('@') are replaced with a random non-zero digit or an empty string. - -Under the hood, this method uses :meth:`random_digit() `, -:meth:`random_digit_not_null() `, -:meth:`random_digit_or_empty() `, -and :meth:`random_digit_not_null_or_empty() ` -to generate the random values. - -Aliases: numerify - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.Numerify(text='Intel Core i%-%%##K vs AMD Ryzen % %%##X')}} - block_example: - fake.Numerify: - text: Intel Core i%-%%##K vs AMD Ryzen % %%##X - -Outputs: - - Example(id=1, inline_example=Intel Core i6-3575K vs AMD Ryzen 7 7294X, block_example=Intel Core i3-4409K vs AMD Ryzen 8 7735X) - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.Numerify(text='!!! !!@ !@! !@@ @!! @!@ @@! @@@')}} - block_example: - fake.Numerify: - text: '!!! !!@ !@! !@@ @!! @!@ @@! @@@' - -Outputs: - - Example(id=1, inline_example=90 1 248 8 751 7 , block_example=4 61 7 926 81 6) - -#### fake: RandomChoices - -Generate a list of objects randomly sampled from ``elements`` with replacement. - -For information on the ``elements`` and ``length`` arguments, please refer to -:meth:`random_elements() ` which -is used under the hood with the ``unique`` argument explicitly set to ``False``. - - - -("a", 0.45), -("b", 0.35), -("c", 0.15), -("d", 0.05), -]) - -("a", 0.45), -("b", 0.35), -("c", 0.15), -("d", 0.05), -]), length=20 - -Aliases: random_choices, randomchoices - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/__init__.py) - -#### fake: RandomDigit - -Generate a random digit (0 to 9). - -Aliases: random_digit, randomdigit - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.RandomDigit}} - block_example: - fake: RandomDigit - -Outputs: - - Example(id=1, inline_example=7, block_example=6) - -#### fake: RandomDigitNotNull - -Generate a random non-zero digit (1 to 9). - -Aliases: random_digit_not_null, randomdigitnotnull - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.RandomDigitNotNull}} - block_example: - fake: RandomDigitNotNull - -Outputs: - - Example(id=1, inline_example=8, block_example=7) - -#### fake: RandomDigitNotNullOrEmpty - -Generate a random non-zero digit (1 to 9) or an empty string. - -This method will return an empty string 50% of the time, -and each digit has a 1/18 chance of being generated. - -:sample size=10: - -Aliases: random_digit_not_null_or_empty, randomdigitnotnullorempty - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.RandomDigitNotNullOrEmpty}} - block_example: - fake: RandomDigitNotNullOrEmpty - -Outputs: - - Example(id=1, inline_example=, block_example=2) - -#### fake: RandomDigitOrEmpty - -Generate a random digit (0 to 9) or an empty string. - -This method will return an empty string 50% of the time, -and each digit has a 1/20 chance of being generated. - -:sample size=10: - -Aliases: random_digit_or_empty, randomdigitorempty - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.RandomDigitOrEmpty}} - block_example: - fake: RandomDigitOrEmpty - -Outputs: - - Example(id=1, inline_example=8, block_example=) - -#### fake: RandomElement - -Generate a randomly sampled object from ``elements``. - -For information on the ``elements`` argument, please refer to -:meth:`random_elements() ` which -is used under the hood with the ``unique`` argument set to ``False`` and the -``length`` argument set to ``1``. - -:sample size=10: elements=OrderedDict([ -("a", 0.45), -("b", 0.35), -("c", 0.15), -("d", 0.05), -]) - -Aliases: random_element, randomelement - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/__init__.py) - -#### fake: RandomElements - -Generate a list of randomly sampled objects from ``elements``. - -Set ``unique`` to ``False`` for random sampling with replacement, and set ``unique`` to -``True`` for random sampling without replacement. - -If ``length`` is set to ``None`` or is omitted, ``length`` will be set to a random -integer from 1 to the size of ``elements``. - -The value of ``length`` cannot be greater than the number of objects -in ``elements`` if ``unique`` is set to ``True``. - -The value of ``elements`` can be any sequence type (``list``, ``tuple``, ``set``, -``string``, etc) or an ``OrderedDict`` type. If it is the latter, the keys will be -used as the objects for sampling, and the values will be used as weighted probabilities -if ``unique`` is set to ``False``. For example: - -.. code-block:: python - - # Random sampling with replacement -fake.random_elements( -elements=OrderedDict([ -("variable_1", 0.5), # Generates "variable_1" 50% of the time -("variable_2", 0.2), # Generates "variable_2" 20% of the time -("variable_3", 0.2), # Generates "variable_3" 20% of the time -("variable_4": 0.1), # Generates "variable_4" 10% of the time -]), unique=False -) - - # Random sampling without replacement (defaults to uniform distribution) -fake.random_elements( -elements=OrderedDict([ -("variable_1", 0.5), -("variable_2", 0.2), -("variable_3", 0.2), -("variable_4": 0.1), -]), unique=True -) - - - - - -("a", 0.45), -("b", 0.35), -("c", 0.15), -("d", 0.05), -]), length=20, unique=False - -("a", 0.45), -("b", 0.35), -("c", 0.15), -("d", 0.05), -]), unique=True - -Aliases: random_elements, randomelements - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/__init__.py) - -#### fake: RandomInt - -Generate a random integer between two integers ``min`` and ``max`` inclusive -while observing the provided ``step`` value. - -This method is functionally equivalent to randomly sampling an integer -from the sequence ``range(min, max + 1, step)``. - -:sample size=10: min=0, max=15 -:sample size=10: min=0, max=15, step=3 - -Aliases: random_int, randomint - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.RandomInt}} - block_example: - fake: RandomInt - -Outputs: - - Example(id=1, inline_example=9558, block_example=3578) - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.RandomInt(min=0, max=15)}} - block_example: - fake.RandomInt: - min: 0 - max: 15 - -Outputs: - - Example(id=1, inline_example=4, block_example=9) - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.RandomInt(min=0, max=15, step=3)}} - block_example: - fake.RandomInt: - min: 0 - max: 15 - step: 3 - -Outputs: - - Example(id=1, inline_example=3, block_example=0) - -#### fake: RandomLetter - -Generate a random ASCII letter (a-z and A-Z). - -Aliases: random_letter, randomletter - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.RandomLetter}} - block_example: - fake: RandomLetter - -Outputs: - - Example(id=1, inline_example=G, block_example=F) - -#### fake: RandomLetters - -Generate a list of random ASCII letters (a-z and A-Z) of the specified ``length``. - -Aliases: random_letters, randomletters - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.RandomLetters}} - block_example: - fake: RandomLetters - -Outputs: - - Example(id=1, inline_example=['P', 'x', 'e', 'q', 'A', 'W', 'f', 'C', 'K', 'C', 'Q', 'C', 'Y', 'F', 'E', 'x'], block_example=['F', 'u', 'D', 'p', 'j', 'j', 'F', 'I', 'y', 'e', 'N', 'T', 'W', 'R', 'U', 'W']) - -#### fake: RandomLowercaseLetter - -Generate a random lowercase ASCII letter (a-z). - -Aliases: random_lowercase_letter, randomlowercaseletter - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.RandomLowercaseLetter}} - block_example: - fake: RandomLowercaseLetter - -Outputs: - - Example(id=1, inline_example=q, block_example=p) - -#### fake: RandomNumber - -Generate a random integer according to the following rules: - -- If ``digits`` is ``None`` (default), its value will be set to a random -integer from 1 to 9. -- If ``fix_len`` is ``False`` (default), all integers that do not exceed -the number of ``digits`` can be generated. -- If ``fix_len`` is ``True``, only integers with the exact number of -``digits`` can be generated. - -Aliases: random_number, randomnumber - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.RandomNumber(fix_len=False)}} - block_example: - fake.RandomNumber: - fix_len: false - -Outputs: - - Example(id=1, inline_example=67013, block_example=54349339) - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.RandomNumber(fix_len=True)}} - block_example: - fake.RandomNumber: - fix_len: true - -Outputs: - - Example(id=1, inline_example=72468, block_example=711720) - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.RandomNumber(digits=3)}} - block_example: - fake.RandomNumber: - digits: 3 - -Outputs: - - Example(id=1, inline_example=913, block_example=929) - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.RandomNumber(digits=3, fix_len=False)}} - block_example: - fake.RandomNumber: - digits: 3 - fix_len: false - -Outputs: - - Example(id=1, inline_example=223, block_example=516) - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.RandomNumber(digits=3, fix_len=True)}} - block_example: - fake.RandomNumber: - digits: 3 - fix_len: true - -Outputs: - - Example(id=1, inline_example=242, block_example=388) - -#### fake: RandomSample - -Generate a list of objects randomly sampled from ``elements`` without replacement. - -For information on the ``elements`` and ``length`` arguments, please refer to -:meth:`random_elements() ` which -is used under the hood with the ``unique`` argument explicitly set to ``True``. - -Aliases: random_sample, randomsample - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/__init__.py) - -#### fake: RandomUppercaseLetter - -Generate a random uppercase ASCII letter (A-Z). - -Aliases: random_uppercase_letter, randomuppercaseletter - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.RandomUppercaseLetter}} - block_example: - fake: RandomUppercaseLetter - -Outputs: - - Example(id=1, inline_example=Q, block_example=P) - -#### fake: RandomizeNbElements - -Generate a random integer near ``number`` according to the following rules: - -- If ``le`` is ``False`` (default), allow generation up to 140% of ``number``. -If ``True``, upper bound generation is capped at 100%. -- If ``ge`` is ``False`` (default), allow generation down to 60% of ``number``. -If ``True``, lower bound generation is capped at 100%. -- If a numerical value for ``min`` is provided, generated values less than ``min`` -will be clamped at ``min``. -- If a numerical value for ``max`` is provided, generated values greater than -``max`` will be clamped at ``max``. -- If both ``le`` and ``ge`` are ``True``, the value of ``number`` will automatically -be returned, regardless of the values supplied for ``min`` and ``max``. - -Aliases: randomize_nb_elements, randomizenbelements - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.RandomizeNbElements(number=100)}} - block_example: - fake.RandomizeNbElements: - number: 100 - -Outputs: - - Example(id=1, inline_example=109, block_example=113) - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.RandomizeNbElements(number=100, ge=True)}} - block_example: - fake.RandomizeNbElements: - number: 100 - ge: true - -Outputs: - - Example(id=1, inline_example=102, block_example=116) - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.RandomizeNbElements(number=100, ge=True, min=120)}} - block_example: - fake.RandomizeNbElements: - number: 100 - ge: true - min: 120 - -Outputs: - - Example(id=1, inline_example=132, block_example=131) - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.RandomizeNbElements(number=100, le=True)}} - block_example: - fake.RandomizeNbElements: - number: 100 - le: true - -Outputs: - - Example(id=1, inline_example=85, block_example=79) - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.RandomizeNbElements(number=100, le=True, max=80)}} - block_example: - fake.RandomizeNbElements: - number: 100 - le: true - max: 80 - -Outputs: - - Example(id=1, inline_example=80, block_example=80) - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.RandomizeNbElements(number=79, le=True, ge=True, min=80)}} - block_example: - fake.RandomizeNbElements: - number: 79 - le: true - ge: true - min: 80 - -Outputs: - - Example(id=1, inline_example=79, block_example=79) - -### Python Fakers - -#### fake: Pybool - -Aliases: pybool - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/python/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.Pybool}} - block_example: - fake: Pybool - -Outputs: - - Example(id=1, inline_example=True, block_example=True) - -#### fake: Pydecimal - -Aliases: pydecimal - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/python/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.Pydecimal}} - block_example: - fake: Pydecimal - -Outputs: - - Example(id=1, inline_example=333018422.10356, block_example=935868384284.7) - -#### fake: Pydict - -Returns a dictionary. - -:nb_elements: number of elements for dictionary -:variable_nb_elements: is use variable number of elements for dictionary -:value_types: type of dictionary values - -Aliases: pydict - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/python/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.Pydict}} - block_example: - fake: Pydict - -Outputs: - - Example(id=1, inline_example={'however': 7230, 'issue': 'tXejffFiKWjvjXrBsGeN', 'across': -9.1092906014666, 'key': 'pNGCiKyJNmNoZgTcnBEu', 'should': 'MsTIkednBgSUNdSogBkf', 'wear': 'todd75@hotmail.com'}, block_example={'certainly': 'elarson@yahoo.com', 'close': datetime.datetime(1991, 8, 28, 21, 39, 37), 'candidate': Decimal('40561592774.2339'), 'same': Decimal('0.66363066127717'), 'camera': 165, 'I': datetime.datetime(1974, 7, 10, 19, 2, 25), 'institution': 'xdavis@gibson.com', 'perhaps': -19796477880609.9, 'management': 7110.96468809015, 'chair': 6293, 'opportunity': 'rHJhWhqkjsZwzLPwkKVb', 'relate': 'bridgetrivera@rich.com', 'firm': 'http://sherman-hartman.com/about.asp', 'health': 'qbrock@hotmail.com'}) - -#### fake: Pyfloat - -Aliases: pyfloat - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/python/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.Pyfloat}} - block_example: - fake: Pyfloat - -Outputs: - - Example(id=1, inline_example=333018422.10356, block_example=935868384284.7) - -#### fake: Pyint - -Aliases: pyint - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/python/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.Pyint}} - block_example: - fake: Pyint - -Outputs: - - Example(id=1, inline_example=7961, block_example=6634) - -#### fake: Pyiterable - -Aliases: pyiterable - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/python/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.Pyiterable}} - block_example: - fake: Pyiterable - -Outputs: - - Example(id=1, inline_example=['tyronecervantes@schultz.info', -57431325491810.6, 1020, 'HgoRcbvzSLJhZvFucyhb', 'https://www.houston.com/category/', Decimal('78.8219282425171')], block_example={'jfrXgYsypWXHjZfEiUXP', Decimal('46809.968437303'), 'vLqkpyXPoDJPxuNwmxWh', 'mjtISFuKgpvWEpsmGHBt', 8328, 'zUXIDleQUOKvpfwDVWvf', 'cherylmcmahon@yahoo.com', 2036, Decimal('39529332399.3'), 'NGCiKyJNmNoZgTcnBEuf', Decimal('-33400472.39132'), 'brycewalls@strickland-blair.com', 'caldwellcaitlyn@lewis.com', 'MbxJbVYLedsbsaYQdUkk'}) - -#### fake: Pylist - -Aliases: pylist - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/python/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.Pylist}} - block_example: - fake: Pylist - -Outputs: - - Example(id=1, inline_example=[1376, 'vfOMbxJbVYLedsbsaYQd', 'kkJWgatbFSjfrXgYsypW', datetime.datetime(2013, 4, 10, 18, 29, 48), 3015, 'http://quinn.com/', 'qmNpvcgbedvCMhvHextX', 'taYUwtXejffFiKWjvjXr', datetime.datetime(1979, 9, 14, 12, 49, 15), 7576, 'nfrost@johnson-benton.info', 'http://www.chavez-galvan.com/tags/tag/posts/home/', 'mariahhebert@yahoo.com'], block_example=['wongwhitney@smith.biz', datetime.datetime(2009, 7, 31, 3, 33, 54), 7284, 'MsTIkednBgSUNdSogBkf', 'todd75@hotmail.com', 'geraldorr@doyle.org', Decimal('-362.522405940924'), 3571, Decimal('-66131725.1010359')]) - -#### fake: Pyset - -Aliases: pyset - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/python/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.Pyset}} - block_example: - fake: Pyset - -Outputs: - - Example(id=1, inline_example={1376, 'nfrost@johnson-benton.info', 'taYUwtXejffFiKWjvjXr', 3015, 'mariahhebert@yahoo.com', datetime.datetime(1979, 9, 14, 12, 49, 15), datetime.datetime(2013, 4, 10, 18, 29, 48), 'kkJWgatbFSjfrXgYsypW', 'vfOMbxJbVYLedsbsaYQd', 'qmNpvcgbedvCMhvHextX', 'http://www.chavez-galvan.com/tags/tag/posts/home/', 7576, 'http://quinn.com/'}, block_example={'geraldorr@doyle.org', Decimal('-362.522405940924'), 'wongwhitney@smith.biz', 'todd75@hotmail.com', 3571, 7284, Decimal('-66131725.1010359'), datetime.datetime(2009, 7, 31, 3, 33, 54), 'MsTIkednBgSUNdSogBkf'}) - -#### fake: Pystr - -Generates a random string of upper and lowercase letters. -:type min_chars: int -:type max_chars: int -:return: String. Random of random length between min and max characters. - -Aliases: pystr - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/python/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.Pystr}} - block_example: - fake: Pystr - -Outputs: - - Example(id=1, inline_example=GRmMglPrQfhKcDVBJbHF, block_example=DutYbbXjgkPWbwfnlHsj) - -#### fake: PystrFormat - -Aliases: pystr_format, pystrformat - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/python/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.PystrFormat}} - block_example: - fake: PystrFormat - -Outputs: - - Example(id=1, inline_example=C9-3877113u, block_example=U0-8018541q) - -#### fake: Pystruct - -Aliases: pystruct - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/python/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.Pystruct}} - block_example: - fake: Pystruct - -Outputs: - - Example(id=1, inline_example=(['AlnRDYPnKrQpTzKvYjZJ', 'ANuZspJKtvkFnBczSvFj', 'GaNPwqXmgqcYwhAuFFQU', 'AwPyLGMUlJalMplCUClp', 'HoHCECnIeqpwakSPaFAf', 'rfzpPsEjOgoRESSZZKyZ', 2775, Decimal('-624.560558663604'), 'ABtOefKYYukvkNLyvsML', 'efFduoNGEJBMQJHIrnoI'], {'more': 'PnYFlpEauZmcjxERRLrI', 'mean': -3380.60709450259, 'raise': 'IPUlkGTQQinWLLRJpTrX', 'woman': 'raymondjacobs@marks.com', 'per': 'qsingleton@hotmail.com', 'direction': 'dwiley@palmer-hays.info', 'medical': 'jimmy52@gmail.com', 'seem': 9318, 'opportunity': Decimal('7816622550.5122'), 'win': Decimal('-3055399609094.3')}, {'likely': {0: 'otXBHKVvOxrMFqEfVbdK', 1: ['WvWAepzTdCCTtyIlHxmm', 'http://singh.biz/homepage/', 'ExvmtRxZXngKbkpmxXzq'], 2: {0: 'pfksTjPmkHNctpoGaWXg', 1: datetime.datetime(1970, 1, 20, 18, 9, 53), 2: [datetime.datetime(2019, 3, 20, 4, 21, 19), 'EGoIizbIEqCmLUsPRhoy']}}, 'successful': {1: 'FUdbrbputMNKRmTxTqxZ', 2: ['QfOxRhpBHrJWrdsahIog', 'irASNEYAkztuzQCKWgLP', 'https://www.spears.com/register.asp'], 3: {1: 'djMgmkbszXrreHUJzGqs', 2: 1542, 3: ['JhDPmefptRyNmKYvScec', 'http://cantu.org/author/']}}, 'can': {2: 'melinda30@gmail.com', 3: [-2971150070.28733, 'HVGSTXNXIMWXYaEXHjir', datetime.datetime(1997, 10, 15, 7, 21, 19)], 4: {2: 'teHuAcZpKPitsiINHMev', 3: Decimal('-3903478892.99996'), 4: ['LXezkrcAngrgTKMZWpFz', 7.17977529165436]}}, 'identify': {3: 'dWgdfLgtXFbfFFDPiDnp', 4: ['http://graham-schmidt.com/main/main/tags/post.htm', 'nxUWoJCUpxEvvkMQHDTS', 'AdLsLrfTUwpuFoEGaiqF'], 5: {3: datetime.datetime(2001, 10, 23, 21, 7, 8), 4: 3321, 5: [994, 8248]}}, 'wrong': {4: 6262, 5: [9966, 3444, 131], 6: {4: 'fAHHfrlrKtqerPRHHTvu', 5: 'http://brennan-dudley.com/', 6: [-48.262033391978, 5463]}}, 'change': {5: 'tVTRrnfOuyedRDijsnha', 6: [7279, -88913121756.539, 'IapbxSUIRyeyLlgZxHZK'], 7: {5: 8851, 6: -60544431.5256728, 7: ['http://www.ferrell.com/terms.php', Decimal('-82.3137650741875')]}}, 'present': {6: 'txXhOTfqojIVkyCoOuft', 7: [datetime.datetime(1995, 12, 29, 0, 20, 55), 58853.2993449084, 32008793.30265], 8: {6: 'bwpcQfqQMwNnvQqPwKjx', 7: 'fjnOoffkdJBcFzUiJkFX', 8: ['VaTLcWeksUwSmKWCVxkR', datetime.datetime(2012, 1, 18, 15, 54, 31)]}}, 'lay': {7: 'natashaherring@watts.com', 8: ['https://hodges.biz/tags/categories/main/', Decimal('87.9261994045045'), 'qOVqzLNoDTdRKRUMIeDb'], 9: {7: 4196, 8: 'AXagmwKEFSdOlOWTBSAT', 9: [Decimal('-1073655449.14833'), 54071212.3645809]}}, 'benefit': {8: -263600384742.957, 9: ['KvGhYNQkRqrITJpQhXKD', 'tWlgjJBZhbcgRSJtyOBg', Decimal('-7.7640121431953')], 10: {8: Decimal('709.678338409695'), 9: 7476, 10: [993, 'kIMaXOkrryujudzakkqA']}}, 'front': {9: 'uaDZZmMjQFQJRhojglex', 10: [145, 'kKcaSVbnsEGYoutRkVIz', 'coUYiMyXVmWbhNoVvYFn'], 11: {9: 1787, 10: 'https://odom.net/main.htm', 11: ['AqBknmSuStqIvQHKYRrx', 'UCCelgqaAasfmInaQCTn']}}}), block_example=(['OXXtemWVJOLAoRkQGPSm', Decimal('28758635.2898326'), 2342, 4044, 'https://graves.org/tag/post/', 1771, 'QuuFCvjVCVBgORMsHOzL', 'NWrGYdSxVtcAWCmJCCml', 'anBHZZLtTIJqQsrEdbwv', 'https://www.hamilton.com/'], {'blue': 'WOFXuxIRpgblNdeqrKwf', 'modern': 'gmueller@gmail.com', 'teacher': 8893, 'account': 3187, 'finally': Decimal('-18247154934.426'), 'same': 6671, 'throw': 6331, 'public': 29116.8304143767, 'single': 'https://ritter-mccoy.com/register.html', 'discussion': 'WMxPLafnTuVegvMMkqgP'}, {'order': {0: 'http://ryan.com/login.jsp', 1: ['https://www.mccall-vasquez.org/posts/categories/search.jsp', 'ksMvjXWSzZdIbrDzwWTU', 'kItUrFRrgsosYSERAWnU'], 2: {0: 'http://www.jenkins-parks.com/', 1: -7529800541539.8, 2: ['CCjKyDWZFAYbiKqzGuEq', 'nKEYyQEsFUlHvhBFButr']}}, 'student': {1: 'YRGgRAEClCyUWZBpeboc', 2: [73334959.7930117, Decimal('-6339158106.71388'), 309050839.29914], 3: {1: 'lHHZBjvmeNaqyhUsNZpt', 2: 'usparks@hotmail.com', 3: ['http://melton-medina.org/category/', 5464]}}, 'executive': {2: Decimal('-49.438926121434'), 3: [datetime.datetime(1999, 11, 21, 5, 44, 5), 'pIaVGadFmrTOATEoYddU', datetime.datetime(1992, 9, 22, 15, 17, 11)], 4: {2: 'PMXrGVmaCwuuJBwJszrB', 3: 1657, 4: [datetime.datetime(2012, 6, 28, 13, 51, 49), 'jWQvXcFsPZpGHqpfXzKO']}}, 'kind': {3: 'http://www.haley-maldonado.com/categories/privacy.php', 4: ['http://bradley-meza.net/search/tags/search/faq/', 'https://www.archer-carpenter.com/posts/tag/list/privacy.php', datetime.datetime(1985, 7, 10, 19, 37, 21)], 5: {3: datetime.datetime(2020, 12, 3, 3, 58, 20), 4: 'YNTymfhoOgZcDDAiySnt', 5: [-86165295881087.6, datetime.datetime(1974, 5, 25, 6, 34, 53)]}}, 'quality': {4: 'http://www.sanders-floyd.com/main/category/login/', 5: [Decimal('5158295364.1217'), 'claysydney@yahoo.com', 1619], 6: {4: 'wallcathy@hinton.org', 5: 9137.47670418247, 6: [datetime.datetime(1984, 4, 3, 2, 1, 37), 'IMBQiNbnexoTcNTGkaeR']}}, 'allow': {5: 'HqGjPKBFwAArotfaNTrp', 6: ['UcjfsRbrWDqTNcTVzGvr', 'heidigutierrez@zimmerman.com', 'xUFsPmEXaEOCmTFvwTJZ'], 7: {5: 'drakesummer@martin.com', 6: Decimal('444.876804221886'), 7: ['jesusrandall@gonzalez.com', 'BauHMCILyGKBobSKTzkk']}}, 'strategy': {6: 'https://hess-hess.com/tag/main/', 7: ['qTwogmFkYTzXcIycKGJl', 'ChDHNOhInFURxoJlKkRc', 'TElVPSMBKzClsvCwVOOo'], 8: {6: -40890567296284.0, 7: 'sgRsEOKCiaERZhVVpyLl', 8: ['BPFYrPDkgzkucwtyQHrb', 'xYMJXbhlNScBWUZIslCE']}}, 'wide': {7: 'gWciUUeILqBHxDmntujX', 8: [-29858635883003.3, 'yeuUzLxzoJkVRnAXSfvt', 'OHnnxvKvUfhNTBCEQRqu'], 9: {7: datetime.datetime(2018, 7, 19, 3, 56, 29), 8: -0.1825490280262, 9: ['tdRlEWsCvfWThwaXErak', 'http://pope.info/search/homepage.jsp']}}, 'your': {8: 2326.8009205109, 9: ['SfBMDlzvgsZchSSfSSzj', Decimal('4.96204389699817'), 'http://foley.com/author/'], 10: {8: 8555, 9: 'barrross@yahoo.com', 10: ['EZJsaXKRmRpJDwnNKDkX', 'hxCMgjRxjMSiaLwRcDSz']}}, 'test': {9: Decimal('652198.966221436'), 10: ['KJQeIvLHqDNVUjvWFemp', 4734, 812], 11: {9: 'rmanning@mcmahon.com', 10: 'fbcYXXDheRDYkmOdIlIP', 11: [Decimal('-47753760363090.5'), 'yharmon@owen.com']}}})) - -#### fake: Pytuple - -Aliases: pytuple - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/python/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.Pytuple}} - block_example: - fake: Pytuple - -Outputs: - - Example(id=1, inline_example=(1376, 'vfOMbxJbVYLedsbsaYQd', 'kkJWgatbFSjfrXgYsypW', datetime.datetime(2013, 4, 10, 18, 29, 48), 3015, 'http://quinn.com/', 'qmNpvcgbedvCMhvHextX', 'taYUwtXejffFiKWjvjXr', datetime.datetime(1979, 9, 14, 12, 49, 15), 7576, 'nfrost@johnson-benton.info', 'http://www.chavez-galvan.com/tags/tag/posts/home/', 'mariahhebert@yahoo.com'), block_example=('wongwhitney@smith.biz', datetime.datetime(2009, 7, 31, 3, 33, 54), 7284, 'MsTIkednBgSUNdSogBkf', 'todd75@hotmail.com', 'geraldorr@doyle.org', Decimal('-362.522405940924'), 3571, Decimal('-66131725.1010359'))) - -### Ssn Fakers - -#### fake: Ein - -Generate a random United States Employer Identification Number (EIN). - -An United States An Employer Identification Number (EIN) is -also known as a Federal Tax Identification Number, and is -used to identify a business entity. EINs follow a format of a -two-digit prefix followed by a hyphen and a seven-digit sequence: - ##-###### - -https://www.irs.gov/businesses/small-businesses-self-employed/employer-id-numbers - -Aliases: ein - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/ssn/en_US/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.Ein}} - block_example: - fake: Ein - -Outputs: - - Example(id=1, inline_example=88-3664860, block_example=76-2336625) - -#### fake: InvalidSsn - -Generate a random invalid United States Social Security Identification Number (SSN). - -Invalid SSNs have the following characteristics: -Cannot begin with the number 9 -Cannot begin with 666 in positions 1 - 3 -Cannot begin with 000 in positions 1 - 3 -Cannot contain 00 in positions 4 - 5 -Cannot contain 0000 in positions 6 - 9 - -https://www.ssa.gov/kc/SSAFactSheet--IssuingSSNs.pdf - -Additionally, return an invalid SSN that is NOT a valid ITIN by excluding certain ITIN related "group" values - -Aliases: invalid_ssn, invalidssn - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/ssn/en_US/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.InvalidSsn}} - block_example: - fake: InvalidSsn - -Outputs: - - Example(id=1, inline_example=516-00-4617, block_example=143-12-0000) - -#### fake: Itin - -Generate a random United States Individual Taxpayer Identification Number (ITIN). - -An United States Individual Taxpayer Identification Number -(ITIN) is a tax processing number issued by the Internal -Revenue Service. It is a nine-digit number that always begins -with the number 9 and has a range of 70-88 in the fourth and -fifth digit. Effective April 12, 2011, the range was extended -to include 900-70-0000 through 999-88-9999, 900-90-0000 -through 999-92-9999 and 900-94-0000 through 999-99-9999. -https://www.irs.gov/individuals/international-taxpayers/general-itin-information - -Aliases: itin - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/ssn/en_US/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.Itin}} - block_example: - fake: Itin - -Outputs: - - Example(id=1, inline_example=917-90-1553, block_example=932-94-8725) - -#### fake: Ssn - -Generate a random United States Taxpayer Identification Number of the specified type. - -If no type is specified, a US SSN is returned. - -Aliases: ssn - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/ssn/en_US/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.Ssn}} - block_example: - fake: Ssn - -Outputs: - - Example(id=1, inline_example=289-18-1554, block_example=634-33-8726) - -### User_Agent Fakers - -#### fake: AndroidPlatformToken - -Generate an Android platform token used in user agent strings. - -Aliases: android_platform_token, androidplatformtoken - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/user_agent/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.AndroidPlatformToken}} - block_example: - fake: AndroidPlatformToken - -Outputs: - - Example(id=1, inline_example=Android 1.5, block_example=Android 2.3.5) - -#### fake: Chrome - -Generate a Chrome web browser user agent string. - -Aliases: chrome - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/user_agent/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.Chrome}} - block_example: - fake: Chrome - -Outputs: - - Example(id=1, inline_example=Mozilla/5.0 (X11; Linux i686) AppleWebKit/531.2 (KHTML, like Gecko) Chrome/63.0.818.0 Safari/531.2, block_example=Mozilla/5.0 (Linux; Android 4.4) AppleWebKit/535.0 (KHTML, like Gecko) Chrome/32.0.844.0 Safari/535.0) - -#### fake: Firefox - -Generate a Mozilla Firefox web browser user agent string. - -Aliases: firefox - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/user_agent/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.Firefox}} - block_example: - fake: Firefox - -Outputs: - - Example(id=1, inline_example=Mozilla/5.0 (X11; Linux x86_64; rv:1.9.7.20) Gecko/2016-10-28 01:20:46 Firefox/12.0, block_example=Mozilla/5.0 (Macintosh; PPC Mac OS X 10 12_8; rv:1.9.5.20) Gecko/2010-01-10 11:18:29 Firefox/3.8) - -#### fake: InternetExplorer - -Generate an IE web browser user agent string. - -Aliases: internet_explorer, internetexplorer - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/user_agent/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.InternetExplorer}} - block_example: - fake: InternetExplorer - -Outputs: - - Example(id=1, inline_example=Mozilla/5.0 (compatible; MSIE 7.0; Windows 98; Trident/5.0), block_example=Mozilla/5.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/5.0)) - -#### fake: IosPlatformToken - -Generate an iOS platform token used in user agent strings. - -Aliases: ios_platform_token, iosplatformtoken - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/user_agent/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.IosPlatformToken}} - block_example: - fake: IosPlatformToken - -Outputs: - - Example(id=1, inline_example=iPhone; CPU iPhone OS 10_3_4 like Mac OS X, block_example=iPhone; CPU iPhone OS 7_1_2 like Mac OS X) - -#### fake: LinuxPlatformToken - -Generate a Linux platform token used in user agent strings. - -Aliases: linux_platform_token, linuxplatformtoken - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/user_agent/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.LinuxPlatformToken}} - block_example: - fake: LinuxPlatformToken - -Outputs: - - Example(id=1, inline_example=X11; Linux x86_64, block_example=X11; Linux x86_64) - -#### fake: LinuxProcessor - -Generate a Linux processor token used in user agent strings. - -Aliases: linux_processor, linuxprocessor - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/user_agent/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.LinuxProcessor}} - block_example: - fake: LinuxProcessor - -Outputs: - - Example(id=1, inline_example=x86_64, block_example=x86_64) - -#### fake: MacPlatformToken - -Generate a MacOS platform token used in user agent strings. - -Aliases: mac_platform_token, macplatformtoken - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/user_agent/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.MacPlatformToken}} - block_example: - fake: MacPlatformToken - -Outputs: - - Example(id=1, inline_example=Macintosh; U; Intel Mac OS X 10 7_4, block_example=Macintosh; Intel Mac OS X 10 6_5) - -#### fake: MacProcessor - -Generate a MacOS processor token used in user agent strings. - -Aliases: mac_processor, macprocessor - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/user_agent/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.MacProcessor}} - block_example: - fake: MacProcessor - -Outputs: - - Example(id=1, inline_example=U; PPC, block_example=U; Intel) - -#### fake: Opera - -Generate an Opera web browser user agent string. - -Aliases: opera - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/user_agent/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.Opera}} - block_example: - fake: Opera - -Outputs: - - Example(id=1, inline_example=Opera/9.95.(X11; Linux x86_64; bhb-IN) Presto/2.9.162 Version/12.00, block_example=Opera/8.51.(X11; Linux i686; the-NP) Presto/2.9.186 Version/11.00) - -#### fake: Safari - -Generate a Safari web browser user agent string. - -Aliases: safari - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/user_agent/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.Safari}} - block_example: - fake: Safari - -Outputs: - - Example(id=1, inline_example=Mozilla/5.0 (Windows; U; Windows NT 6.1) AppleWebKit/535.16.7 (KHTML, like Gecko) Version/5.1 Safari/535.16.7, block_example=Mozilla/5.0 (iPod; U; CPU iPhone OS 3_0 like Mac OS X; fa-IR) AppleWebKit/531.47.3 (KHTML, like Gecko) Version/3.0.5 Mobile/8B112 Safari/6531.47.3) - -#### fake: UserAgent - -Generate a random web browser user agent string. - -Aliases: user_agent, useragent - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/user_agent/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.UserAgent}} - block_example: - fake: UserAgent - -Outputs: - - Example(id=1, inline_example=Mozilla/5.0 (Windows NT 5.0; the-NP; rv:1.9.1.20) Gecko/2016-08-28 10:17:44 Firefox/3.8, block_example=Mozilla/5.0 (Macintosh; Intel Mac OS X 10 5_8; rv:1.9.5.20) Gecko/2020-03-30 18:10:19 Firefox/3.8) - -#### fake: WindowsPlatformToken - -Generate a Windows platform token used in user agent strings. - -Aliases: windows_platform_token, windowsplatformtoken - -Source: [faker](https://github.com/joke2k/faker/tree/master/faker/providers/user_agent/__init__.py) - -##### Samples - -Recipe: - - - var: snowfakery_locale - value: en_US - - object: Example - fields: - inline_example: ${{fake.WindowsPlatformToken}} - block_example: - fake: WindowsPlatformToken - -Outputs: - - Example(id=1, inline_example=Windows NT 5.2, block_example=Windows NT 5.1) - diff --git a/examples/faker_in_formula.recipe.yml b/examples/faker_in_formula.recipe.yml new file mode 100644 index 00000000..7274f3b3 --- /dev/null +++ b/examples/faker_in_formula.recipe.yml @@ -0,0 +1,3 @@ +- object: Account + fields: + Name: ${{fake.State}} State University diff --git a/examples/parameters.recipe.yml b/examples/parameters.recipe.yml new file mode 100644 index 00000000..0badf01c --- /dev/null +++ b/examples/parameters.recipe.yml @@ -0,0 +1,3 @@ +- object: Example + fields: + gibberish_words: ${{fake.Sentence(nb_words=10, variable_nb_words=False)}} diff --git a/examples/parameters_block.recipe.yml b/examples/parameters_block.recipe.yml new file mode 100644 index 00000000..15ea0c46 --- /dev/null +++ b/examples/parameters_block.recipe.yml @@ -0,0 +1,6 @@ +- object: Example + fields: + gibberish_words: + fake.Sentence: + nb_words: 10 + variable_nb_words: False diff --git a/examples/salesforce/simple_account.recipe.yml b/examples/salesforce/simple_account.recipe.yml new file mode 100644 index 00000000..147621f8 --- /dev/null +++ b/examples/salesforce/simple_account.recipe.yml @@ -0,0 +1,18 @@ +- object: Account + fields: + Name: + fake: Company + Description: + fake: CatchPhrase + BillingStreet: + fake: StreetAddress + BillingCity: + fake: City + BillingState: + fake: State + BillingPostalCode: + fake: PostalCode + BillingCountry: + fake: CurrentCountry + Phone: + fake: PhoneNumber diff --git a/examples/salesforce/simple_account_french.recipe.yml b/examples/salesforce/simple_account_french.recipe.yml new file mode 100644 index 00000000..72dd3104 --- /dev/null +++ b/examples/salesforce/simple_account_french.recipe.yml @@ -0,0 +1,20 @@ +- var: snowfakery_locale + value: fr_FR +- object: Account + fields: + Name: + fake: Company + Description: + fake: CatchPhrase + BillingStreet: + fake: StreetAddress + BillingCity: + fake: City + BillingState: + fake: State + BillingPostalCode: + fake: PostalCode + BillingCountry: + fake: CurrentCountry + Phone: + fake: PhoneNumber diff --git a/examples/salesforce/simple_account_random.recipe.yml b/examples/salesforce/simple_account_random.recipe.yml new file mode 100644 index 00000000..f1d7ec3d --- /dev/null +++ b/examples/salesforce/simple_account_random.recipe.yml @@ -0,0 +1,26 @@ +- var: snowfakery_locale + value: + random_choice: + - ja_JP # Japanese + - en_CA # Canadian English + - fr_FR # French from France + - fr_CA # Canadian Frencch + - de_DE # German from Germany +- object: Account + fields: + Name: + fake: Company + Description: + fake: CatchPhrase + BillingStreet: + fake: StreetAddress + BillingCity: + fake: City + BillingState: + fake: State + BillingPostalCode: + fake: PostalCode + BillingCountry: + fake: CurrentCountry + Phone: + fake: PhoneNumber diff --git a/snowfakery/fakedata/fake_data_generator.py b/snowfakery/fakedata/fake_data_generator.py index 30a7184c..6ee72ad6 100644 --- a/snowfakery/fakedata/fake_data_generator.py +++ b/snowfakery/fakedata/fake_data_generator.py @@ -26,6 +26,14 @@ def realistic_maybe_real_email(self): """ return self.f.email() + def state(self): + """Return a state, province or other appropriate administrative unit""" + return self.f.administrative_unit() + + def postalcode(self): + """Return watever counts as a postalcode for a particular locale""" + return self.f.postcode() + # we will use this to exclude Faker's internal book-keeping methods # from our faker interface diff --git a/tools/faker_docs_utils/fakedata_header_full.md b/tools/faker_docs_utils/fakedata_header_full.md new file mode 100644 index 00000000..2fcad2d1 --- /dev/null +++ b/tools/faker_docs_utils/fakedata_header_full.md @@ -0,0 +1,165 @@ +# Fake data + +## Overview + +Fake data comes in a few different flavours. Let's start with the +most common pattern: + +```yaml +# examples/salesforce/simple_account.recipe.yml +- object: Account + fields: + Name: + fake: Company + Description: + fake: CatchPhrase + BillingStreet: + fake: StreetAddress + BillingCity: + fake: City + BillingState: + fake: State + BillingPostalCode: + fake: PostalCode + BillingCountry: + fake: CurrentCountry + Phone: + fake: PhoneNumber +``` + +So the first obvious question is where you find these names. The answer +is you can scroll down on this page to see a long list with descriptions. + +The description above might generate output like this: + +```json +Account(id=1, Name=Nelson-Deleon, Description=Secured bandwidth-monitored moratorium, BillingStreet=2187 Kerry Way, BillingCity=Rangelland, BillingState=Colorado, BillingPostalCode=08388, BillingCountry=United States, Phone=001-738-530-9719) +``` + +## Formulas + +Sometimes you might want to combine the fake data with other data +in a single field. You can use formula syntaax for this. + +```yaml +# examples/faker_in_formula.recipe.yml +- object: Account + fields: + Name: ${{fake.State}} State University +``` + +Some complex faker definitions can also use parameters. The +documentation says what parameters are allowed. The docs +for [fake: sentence](#fake-sentence) define `nb_words` and +`variable_nb_words`, for example. + +```yaml +# examples/parameters.recipe.yml +- object: Example + fields: + gibberish_words: ${{fake.Sentence(nb_words=10, variable_nb_words=False)}} +``` + +## Block fakers with parameters + +If you'd rather not use the formula syntax (${{ blah }}) there is also +a nested syntax for that: + +```yaml +# examples/parameters_block.recipe.yml +- object: Example + fields: + gibberish_words: + fake.Sentence: + nb_words: 10 + variable_nb_words: False +``` + +## Localization + +Let's say that you want to generate fake data for France instead of the +United States. + +You do so by setting the special `snowfakery_locale` "variable" like this. + +```yaml +# examples/salesforce/simple_account_french.recipe.yml + +- var: snowfakery_locale + value: fr_FR +- object: Account + fields: + Name: + fake: Company + Description: + fake: CatchPhrase + BillingStreet: + fake: StreetAddress + BillingCity: + fake: City + BillingState: + fake: State + BillingPostalCode: + fake: PostalCode + BillingCountry: + fake: CurrentCountry + Phone: + fake: PhoneNumber +``` + +This will translate the State to the appropriate administrative unit in +France. `CurrentCountry` will be France, not `United States`. The Catch +Phrase will be in French and so forth. + +For example: + +```json +Account(id=1, Name=Parent Auger S.A.S., Description=Le confort de rouler de manière sûre, BillingStreet=54, rue de Bailly, BillingCity=Charrier, BillingState=Île-de-France, BillingPostalCode=72902, BillingCountry=France, Phone=08 05 11 90 19) +``` + +We can do many countries. For example, Japanese (ja_JP locale): + +```json +Account(id=1, Name=有限会社山下電気, Description=Inverse 24hour pricing structure, BillingStreet=040 佐々木 Street, BillingCity=横浜市金沢区, BillingState=福岡県, BillingPostalCode=181-5538, BillingCountry=Japan, Phone=070-4156-5072) +``` + +We can even pick the locale randomly: + +```yaml +# examples/salesforce/simple_account_random.recipe.yml +- var: snowfakery_locale + value: + random_choice: + - ja_JP # Japanese + - en_CA # Canadian English + - fr_FR # French from France + - fr_CA # Canadian Frencch + - de_DE # German from Germany +- object: Account + fields: + Name: + fake: Company + Description: + fake: CatchPhrase + BillingStreet: + fake: StreetAddress + BillingCity: + fake: City + BillingState: + fake: State + BillingPostalCode: + fake: PostalCode + BillingCountry: + fake: CurrentCountry + Phone: + fake: PhoneNumber +``` + +## Fake Dates and Numbers + +The main Snowfakery documentation describes how to fake +[dates](index.md#date-between) and [numbers](index.md#random-number). + +That's it. Those are all of the concepts you need. + +## Index of Fake Datatypes diff --git a/tools/faker_docs_utils/fakedata_header_short.md b/tools/faker_docs_utils/fakedata_header_short.md new file mode 100644 index 00000000..2d1c317b --- /dev/null +++ b/tools/faker_docs_utils/fakedata_header_short.md @@ -0,0 +1,10 @@ +# Fake Data: {locale}\n + +The basic concepts of fake data are described in +the [main docs](../index.md#fake-data). + +Our fake data can be localized to many languages. We have +[detailed docs](https://snowfakery.readthedocs.io/en/feature-fake-data-docs/locales.html) +about the other languages. + +Current Locale: {locale} ({current_country})\n diff --git a/tools/faker_docs_utils/faker_markdown.py b/tools/faker_docs_utils/faker_markdown.py index b5ce548e..8c93532c 100644 --- a/tools/faker_docs_utils/faker_markdown.py +++ b/tools/faker_docs_utils/faker_markdown.py @@ -49,7 +49,10 @@ def format_link(locale: str): return " ".join(link for link in links if link) -def generate_markdown_for_fakers(outfile, locale): +standard_header = (Path(__file__).parent / "fakedata_header_short.md").read_text() + + +def generate_markdown_for_fakers(outfile, locale: str, header: str = standard_header): faker = Faker(locale) fd = FakeData(faker) @@ -58,20 +61,7 @@ def generate_markdown_for_fakers(outfile, locale): def output(*args, **kwargs): print(*args, **kwargs, file=outfile) - output(f"# Fake Data: {locale}\n") - - output( - f"""The basic concepts of fake data are described in -the [main docs](index.md#fake-data). - -Our fake data can be localized to many languages. We have -[detailed docs](https://snowfakery.readthedocs.io/en/feature-fake-data-docs/locales.html) -about the other languages. - -Current Locale: {locale} ({faker.current_country()})\n - -""" - ) + output(header.format(locale=locale, current_country=faker.current_country())) output("[TOC]\n") @@ -111,8 +101,6 @@ def output_faker(name, data, output, locale): samples = yaml_samples_for_docstring(name, data.fullname, data.doc, locale) samples = list(filter(None, samples)) if samples: - output() - output("##### Samples") output() for sample in samples: yaml, out = sample diff --git a/tools/faker_docs_utils/mkdocs_plugins/main_mkdocs_plugin.py b/tools/faker_docs_utils/mkdocs_plugins/main_mkdocs_plugin.py index 9888803d..a2110413 100644 --- a/tools/faker_docs_utils/mkdocs_plugins/main_mkdocs_plugin.py +++ b/tools/faker_docs_utils/mkdocs_plugins/main_mkdocs_plugin.py @@ -37,9 +37,13 @@ def on_pre_build(self, config): generate_locales_index, ) + fakerdocs_md_header = ( + root_dir / "tools/faker_docs_utils/fakedata_header_full.md" + ) + main_header = Path(fakerdocs_md_header).read_text() fakerdocs_md = root_dir / "docs/fakedata.md" with fakerdocs_md.open("w") as f: - generate_markdown_for_fakers(f, "en_US") + generate_markdown_for_fakers(f, "en_US", main_header) if self.config.get("build_locales"): generate_markdown_for_all_locales(faker_docs_dir) From 3de282aa04798db0c3dbb93732dcf585b055e615 Mon Sep 17 00:00:00 2001 From: Paul Prescod Date: Mon, 14 Jun 2021 02:11:24 -0700 Subject: [PATCH 12/53] Centralize definition of faker --- docs/index.md | 90 ++----------------- .../faker_docs_utils/fakedata_header_full.md | 34 +++++++ .../faker_docs_utils/fakedata_header_short.md | 2 +- 3 files changed, 43 insertions(+), 83 deletions(-) diff --git a/docs/index.md b/docs/index.md index 903fac41..d024e85b 100644 --- a/docs/index.md +++ b/docs/index.md @@ -245,27 +245,8 @@ You can generate many kinds of fake data using the `fake` function: You can fake all sorts of stuff. Names, addresses, Latin text, English sentences, URLs, etc. -The complete list is in [it's own document](fakedata.md) - -For example, you can fake a user account like this: - -```yaml -# examples/salesforce/simple-user.yml -- object: User - fields: - Username: - fake: Username - FirstName: - fake: FirstName - LastName: - fake: LastName - Email: - fake: Email - Alias: - fake: Alias -``` - -It doesn't matter if you use upper or lower case for fake names. +The complete list, along with other related features, can be found in +the [Fake Data Tutorial](fakedata.md) ### Friends @@ -552,7 +533,8 @@ Create a reference to a random, already-created row from some table. - object: Owner count: 10 fields: - name: fake.name + name: + fake: Name - object: Pet count: 10 fields: @@ -576,66 +558,9 @@ github issue. ### `fake` -FIXME: - -You would install that provider like this: - -```s -$ pip install faker_microservice -``` - -Here are some Python Faker providers: - - - -And you could make your own providers as well. - -Fake can be called as an inline function in an expression: - -```yaml -FullName: ${{fake.FirstName}} Johnson -``` - -You can also call these functions with arguments as described in Faker's [documentation](https://faker.readthedocs.io/en/master/providers.html) - -```yaml -- object: Example - field: - country: ${{fake.country_code(representation='alpha-2')}} -``` - -Or: - -```yaml -- object: Example - field: - country: - fake.country_code: - representation: 'alpha-2' -``` - -### International Fakes - -You can specify internationally appropriate fakes for many different kind of names (e.g. person, company) by setting the snowfakery_locale this: - -```yaml -- var: snowfakery_locale - value: no_NO -- object: person - fields: - name: - fake: name -- var: snowfakery_locale - value: fr_FR -- object: person - fields: - name: - fake: name -``` - -This will generate a “typical” Norwegian first name for the first person object and a French name for the second person object. +Generate fake data. This function is defined in detail +in the [Fake Data Tutorial](fakedata.md) -You can infer which Faker providers are internationalizable by looking through the Faker [repository](https://github.com/joke2k/faker/tree/master/faker/providers) and seeing which directories have localizations. For example there are only three localizations of [credit card](https://github.com/joke2k/faker/tree/master/faker/providers) (who knew that credit cards were different in Iran and Russia) and dozens of localizations for [person name](https://github.com/joke2k/faker/tree/master/faker/providers/person). ### `date_between` @@ -959,7 +884,8 @@ a single recipe. #### `fake:` and `fake.` -The `fake:` function and `fake.` namespace both generate fake data as described elsewhere in this documentation. +The `fake:` block function and `fake.` namespace both generate +fake data as described in the [Fake Data Tutorial](fakedata.md). ```yaml # examples/two_fakers.yml diff --git a/tools/faker_docs_utils/fakedata_header_full.md b/tools/faker_docs_utils/fakedata_header_full.md index 2fcad2d1..9d32ad87 100644 --- a/tools/faker_docs_utils/fakedata_header_full.md +++ b/tools/faker_docs_utils/fakedata_header_full.md @@ -36,6 +36,8 @@ The description above might generate output like this: Account(id=1, Name=Nelson-Deleon, Description=Secured bandwidth-monitored moratorium, BillingStreet=2187 Kerry Way, BillingCity=Rangelland, BillingState=Colorado, BillingPostalCode=08388, BillingCountry=United States, Phone=001-738-530-9719) ``` +It doesn't matter if you use upper or lower case for fake names. + ## Formulas Sometimes you might want to combine the fake data with other data @@ -77,6 +79,10 @@ a nested syntax for that: ## Localization +Our fake data can be localized to many languages. We have +[detailed docs](https://snowfakery.readthedocs.io/en/feature-fake-data-docs/locales.html) +about how to use fake data in each of the other languages. + Let's say that you want to generate fake data for France instead of the United States. @@ -162,4 +168,32 @@ The main Snowfakery documentation describes how to fake That's it. Those are all of the concepts you need. +## Custom Faker Providers + +You can also include Faker extension libraries ("Providers") after +you’ve added them to your Python install: + +```yaml + - plugin: faker_microservice.Provider + - object: OBJ + fields: + service_name: + fake: + microservice +``` + +You would install that provider like this: + +```s +$ pip install faker_microservice +``` + +Here are some Python Faker providers: + + + +And you could make your own providers as well. Aaron Crossman +has written [a tutorial](https://spinningcode.org/2021/06/snowfakery-custom-plugins-part-2/) +about that process. + ## Index of Fake Datatypes diff --git a/tools/faker_docs_utils/fakedata_header_short.md b/tools/faker_docs_utils/fakedata_header_short.md index 2d1c317b..d4960e90 100644 --- a/tools/faker_docs_utils/fakedata_header_short.md +++ b/tools/faker_docs_utils/fakedata_header_short.md @@ -1,7 +1,7 @@ # Fake Data: {locale}\n The basic concepts of fake data are described in -the [main docs](../index.md#fake-data). +the [main tutorial](../fakedata.md#fake-data). Our fake data can be localized to many languages. We have [detailed docs](https://snowfakery.readthedocs.io/en/feature-fake-data-docs/locales.html) From 88d60215dc62e2545ec2dc539c7211adda677ab6 Mon Sep 17 00:00:00 2001 From: Paul Prescod Date: Mon, 14 Jun 2021 02:15:57 -0700 Subject: [PATCH 13/53] More prominent link to SF Docs --- docs/salesforce.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/docs/salesforce.md b/docs/salesforce.md index ff64ff77..838cfdb5 100644 --- a/docs/salesforce.md +++ b/docs/salesforce.md @@ -7,7 +7,11 @@ There are several examples [in the Snowfakery repository](https://github.com/SFD ## Using Snowfakery within CumulusCI The process of actually generating the data into a Salesforce -org happens through CumulusCI. +org happens through CumulusCI. The majority of the documentation +on using Snowfakery with CumulusCI is in +[the Generate Data section of the CumulusCI documentation](https://cumulusci.readthedocs.io/en/latest/data.html?highlight=snowfakery#generate-fake-data). + +A summarized overview follows. [CumulusCI](http://www.github.com/SFDO-Tooling/CumulusCI) is a tool and framework for building portable automation for @@ -17,8 +21,6 @@ creates Snowfakery. The easiest way to learn about CumulusCI (and to learn how to install it) is with its [Trailhead Trail](https://trailhead.salesforce.com/en/content/learn/trails/build-applications-with-cumulusci). -CumulusCI's documentation [describes](https://cumulusci.readthedocs.io/en/latest/data.html?highlight=snowfakery#generate-fake-data) -how to use it with Snowfakery. Here is a short example: ```s $ cci task run generate_and_load_from_yaml -o generator_yaml examples/salesforce/Contact.recipe.yml -o num_records 300 -o num_records_tablename Contact --org qa From 5b6459cbbe1ac9dc3b3faf6eaf8db6c498d0c35e Mon Sep 17 00:00:00 2001 From: Paul Prescod Date: Mon, 14 Jun 2021 02:22:18 -0700 Subject: [PATCH 14/53] Use H5 to avoid TOC --- tools/faker_docs_utils/fakedata_header_full.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tools/faker_docs_utils/fakedata_header_full.md b/tools/faker_docs_utils/fakedata_header_full.md index 9d32ad87..02f7a0a6 100644 --- a/tools/faker_docs_utils/fakedata_header_full.md +++ b/tools/faker_docs_utils/fakedata_header_full.md @@ -1,6 +1,6 @@ # Fake data -## Overview +##### Overview Fake data comes in a few different flavours. Let's start with the most common pattern: @@ -38,7 +38,7 @@ Account(id=1, Name=Nelson-Deleon, Description=Secured bandwidth-monitored morato It doesn't matter if you use upper or lower case for fake names. -## Formulas +##### Formulas Sometimes you might want to combine the fake data with other data in a single field. You can use formula syntaax for this. @@ -62,7 +62,7 @@ for [fake: sentence](#fake-sentence) define `nb_words` and gibberish_words: ${{fake.Sentence(nb_words=10, variable_nb_words=False)}} ``` -## Block fakers with parameters +##### Block fakers with parameters If you'd rather not use the formula syntax (${{ blah }}) there is also a nested syntax for that: @@ -77,7 +77,7 @@ a nested syntax for that: variable_nb_words: False ``` -## Localization +##### Localization Our fake data can be localized to many languages. We have [detailed docs](https://snowfakery.readthedocs.io/en/feature-fake-data-docs/locales.html) @@ -161,14 +161,14 @@ We can even pick the locale randomly: fake: PhoneNumber ``` -## Fake Dates and Numbers +##### Fake Dates and Numbers The main Snowfakery documentation describes how to fake [dates](index.md#date-between) and [numbers](index.md#random-number). That's it. Those are all of the concepts you need. -## Custom Faker Providers +##### Custom Faker Providers You can also include Faker extension libraries ("Providers") after you’ve added them to your Python install: From 4a49743609e453b3dc9de3aec2d5be127de6021e Mon Sep 17 00:00:00 2001 From: Paul Prescod Date: Mon, 14 Jun 2021 02:38:25 -0700 Subject: [PATCH 15/53] Docs about docs --- CONTRIBUTING.rst | 5 +++++ Makefile | 1 + mkdocs.yml | 1 + .../faker_docs_utils/mkdocs_plugins/main_mkdocs_plugin.py | 8 +++++++- 4 files changed, 14 insertions(+), 1 deletion(-) diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index 89e85458..2efa523d 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -71,6 +71,11 @@ Or you could make it outside of the project repo. $ pytest + Test the documentation like this: + + $ make docs + $ open build/html/index.html + 7. Your new code should also have meaningful tests. One way to double check that your tests cover everything is to ensure that your new code has test code coverage: diff --git a/Makefile b/Makefile index c9867a59..66c47281 100644 --- a/Makefile +++ b/Makefile @@ -5,6 +5,7 @@ update-deps: dev-install: pip-sync requirements/*.txt +# set SF_MKDOCS_BUILD_LOCALES=False to skip building all locales docs: .FORCE python -m mkdocs build --clean --site-dir build/html --config-file mkdocs.yml diff --git a/mkdocs.yml b/mkdocs.yml index 3fcaa501..1646870f 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -18,3 +18,4 @@ plugins: - snowfakery_fakes: build_locales: True # do or do not generate locales # should be True on the fake-data-docs branch + # set SF_MKDOCS_BUILD_LOCALES to overide diff --git a/tools/faker_docs_utils/mkdocs_plugins/main_mkdocs_plugin.py b/tools/faker_docs_utils/mkdocs_plugins/main_mkdocs_plugin.py index a2110413..066d61da 100644 --- a/tools/faker_docs_utils/mkdocs_plugins/main_mkdocs_plugin.py +++ b/tools/faker_docs_utils/mkdocs_plugins/main_mkdocs_plugin.py @@ -45,6 +45,12 @@ def on_pre_build(self, config): with fakerdocs_md.open("w") as f: generate_markdown_for_fakers(f, "en_US", main_header) - if self.config.get("build_locales"): + build_locales_env = os.environ.get("SF_MKDOCS_BUILD_LOCALES") + if build_locales_env: + build_locales = build_locales_env != "False" + else: + build_locales = self.config.get("build_locales") + + if build_locales: generate_markdown_for_all_locales(faker_docs_dir) generate_locales_index("docs/locales.md") From 32b9dc05f0feb51ec55305308c646b1f161ebe2d Mon Sep 17 00:00:00 2001 From: Paul Prescod Date: Mon, 14 Jun 2021 12:22:34 -0700 Subject: [PATCH 16/53] Add comment --- mkdocs.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mkdocs.yml b/mkdocs.yml index 1646870f..c4ce39d0 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -16,6 +16,6 @@ markdown_extensions: plugins: - search - snowfakery_fakes: - build_locales: True # do or do not generate locales - # should be True on the fake-data-docs branch + build_locales: True # do generate locales # set SF_MKDOCS_BUILD_LOCALES to overide + # future versions MAY turn off locale-info-building on main branch From f08932f7f2206d5fb166d2f2852e27f2cf5509c1 Mon Sep 17 00:00:00 2001 From: Paul Prescod Date: Mon, 14 Jun 2021 13:01:21 -0700 Subject: [PATCH 17/53] Remove myst. I don't seem to need it. --- requirements/dev.in | 3 +-- requirements/dev.txt | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/requirements/dev.in b/requirements/dev.in index a962bac6..ef709c0f 100644 --- a/requirements/dev.in +++ b/requirements/dev.in @@ -3,13 +3,12 @@ black coverage coveralls flake8 -# myst-parser # is this actually needed??? mkdocs pip-tools pre-commit pytest pytest-cov -Sphinx<4 # pin this until Myst is happy with Sphinx 4 +Sphinx typeguard==2.10.0 # do not upgrade until #181 is fixed faker-microservice tox diff --git a/requirements/dev.txt b/requirements/dev.txt index 408349ee..45dd637b 100644 --- a/requirements/dev.txt +++ b/requirements/dev.txt @@ -41,7 +41,7 @@ distlib==0.3.2 # via virtualenv docopt==0.6.2 # via coveralls -docutils==0.16 +docutils==0.17.1 # via sphinx faker-microservice==2.0.0 # via -r requirements/dev.in @@ -189,7 +189,7 @@ six==1.16.0 # virtualenv snowballstemmer==2.1.0 # via sphinx -sphinx==3.5.4 +sphinx==4.0.2 # via -r requirements/dev.in sphinxcontrib-applehelp==1.0.2 # via sphinx From 2a90f0ce958d241628b9051bb1d209a6c8629a0b Mon Sep 17 00:00:00 2001 From: Paul Prescod Date: Mon, 14 Jun 2021 13:29:28 -0700 Subject: [PATCH 18/53] Reduce use of # pragma no cover --- snowfakery/data_gen_exceptions.py | 2 +- snowfakery/object_rows.py | 5 +++-- tests/test_exceptions.py | 13 +++++++++++++ tests/test_object_rows.py | 9 +++++++++ 4 files changed, 26 insertions(+), 3 deletions(-) create mode 100644 tests/test_exceptions.py create mode 100644 tests/test_object_rows.py diff --git a/snowfakery/data_gen_exceptions.py b/snowfakery/data_gen_exceptions.py index ff685cc8..e064d3db 100644 --- a/snowfakery/data_gen_exceptions.py +++ b/snowfakery/data_gen_exceptions.py @@ -15,7 +15,7 @@ def __init__(self, message, filename=None, line_num=None): def __str__(self): if self.line_num: location = f"\n near {self.filename}:{self.line_num}" - elif self.filename: # pragma: no cover + elif self.filename: location = f"\n in {self.filename}" else: location = "" diff --git a/snowfakery/object_rows.py b/snowfakery/object_rows.py index 87ad5f62..c9dc90d1 100644 --- a/snowfakery/object_rows.py +++ b/snowfakery/object_rows.py @@ -1,6 +1,7 @@ from enum import Enum, auto import yaml +import snowfakery # noqa from .utils.yaml_utils import SnowfakeryDumper IdManager = "snowfakery.data_generator_runtime.IdManager" @@ -73,7 +74,7 @@ class NicknameSlot(ObjectReference): id_manager: IdManager allocated_id: int = None - def __init__(self, tablename, id_manager): + def __init__(self, tablename: str, id_manager: IdManager): self._tablename = tablename self.id_manager = id_manager @@ -100,5 +101,5 @@ def status(self): elif self.allocated_id == SlotState.CONSUMED: return SlotState.CONSUMED - def __repr__(self): # pragma: no cover + def __repr__(self): return f"" diff --git a/tests/test_exceptions.py b/tests/test_exceptions.py new file mode 100644 index 00000000..7e67b11a --- /dev/null +++ b/tests/test_exceptions.py @@ -0,0 +1,13 @@ +from snowfakery.data_gen_exceptions import DataGenError + + +class TestExceptions: + def test_stringify_DataGenError(self): + val = str(DataGenError("Blah", "foo.yml", 25)) + assert "Blah" in val + assert "foo.yml" in val + assert "25" in val + + val = str(DataGenError("Blah", "foo.yml")) + assert "Blah" in val + assert "foo.yml" in val diff --git a/tests/test_object_rows.py b/tests/test_object_rows.py new file mode 100644 index 00000000..faf5ce66 --- /dev/null +++ b/tests/test_object_rows.py @@ -0,0 +1,9 @@ +from unittest.mock import Mock + +from snowfakery.object_rows import NicknameSlot + + +class TestNicknameSlot: + def test_repr(self): + nns = NicknameSlot("Account", Mock()) + assert "Account" in repr(nns) From 5a37cc705770e0abca1f1ad90e7593178a7083a7 Mon Sep 17 00:00:00 2001 From: Paul Prescod Date: Mon, 14 Jun 2021 14:18:01 -0700 Subject: [PATCH 19/53] Line wrap and text --- docs/stylesheets/extra.css | 4 ++++ mkdocs.yml | 2 ++ tools/faker_docs_utils/fakedata_header_full.md | 4 +++- 3 files changed, 9 insertions(+), 1 deletion(-) create mode 100644 docs/stylesheets/extra.css diff --git a/docs/stylesheets/extra.css b/docs/stylesheets/extra.css new file mode 100644 index 00000000..c2a1dfda --- /dev/null +++ b/docs/stylesheets/extra.css @@ -0,0 +1,4 @@ +code { + white-space : pre-wrap !important; + } + \ No newline at end of file diff --git a/mkdocs.yml b/mkdocs.yml index c4ce39d0..9a7b5571 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -9,6 +9,8 @@ nav: - Fake Data: fakedata.md - embedding.md - extending.md +extra_css: + - stylesheets/extra.css markdown_extensions: - toc: permalink: True diff --git a/tools/faker_docs_utils/fakedata_header_full.md b/tools/faker_docs_utils/fakedata_header_full.md index 02f7a0a6..c00f5b53 100644 --- a/tools/faker_docs_utils/fakedata_header_full.md +++ b/tools/faker_docs_utils/fakedata_header_full.md @@ -83,6 +83,8 @@ Our fake data can be localized to many languages. We have [detailed docs](https://snowfakery.readthedocs.io/en/feature-fake-data-docs/locales.html) about how to use fake data in each of the other languages. +The default locale is `en_US`: United Statesian Engish. + Let's say that you want to generate fake data for France instead of the United States. @@ -139,7 +141,7 @@ We can even pick the locale randomly: - ja_JP # Japanese - en_CA # Canadian English - fr_FR # French from France - - fr_CA # Canadian Frencch + - fr_CA # Canadian French - de_DE # German from Germany - object: Account fields: From 6fecc1a486a83b4a03c19ee38ee107e4a3636b50 Mon Sep 17 00:00:00 2001 From: Paul Prescod Date: Tue, 15 Jun 2021 03:38:52 -0700 Subject: [PATCH 20/53] Allow user to repeat recipe by specifying reps --- snowfakery/api.py | 13 +++++++++---- snowfakery/cli.py | 25 +++++++++++++++++++++++-- tests/test_cli.py | 6 ++++++ 3 files changed, 38 insertions(+), 6 deletions(-) diff --git a/snowfakery/api.py b/snowfakery/api.py index 750990f5..5441ad83 100644 --- a/snowfakery/api.py +++ b/snowfakery/api.py @@ -43,6 +43,8 @@ file_extensions = tuple(OUTPUT_FORMATS.keys()) +COUNT_REPS = "__REPS__" + class SnowfakeryApplication: """Base class for all applications which embed Snowfakery as a library, @@ -50,9 +52,10 @@ class SnowfakeryApplication: stopping_criteria = None starting_id = 0 + rep_count = 0 def __init__(self, stopping_criteria: StoppingCriteria = None): - self.stopping_criteria = stopping_criteria + self.stopping_criteria = stopping_criteria or StoppingCriteria(COUNT_REPS, 1) def echo(self, message=None, file=None, nl=True, err=False, color=None): """Write something to a virtual stdout or stderr. @@ -72,7 +75,7 @@ def stopping_tablename(self): This is used by Snowfakery to validate that the provided recipe will not generate forever due to a misspelling the stopping tablename.""" - if self.stopping_criteria: + if self.stopping_criteria.tablename != COUNT_REPS: return self.stopping_criteria.tablename def ensure_progress_was_made(self, id_manager): @@ -94,11 +97,13 @@ def ensure_progress_was_made(self, id_manager): def check_if_finished(self, id_manager): "Check whether we've finished making as many objects as we promised" # if nobody told us how much to make, finish after first run - if not self.stopping_criteria: - return True + self.rep_count += 1 target_table, count = self.stopping_criteria + if target_table == COUNT_REPS: + return self.rep_count >= count + # Snowfakery processes can be restarted. We would need # to keep track of where we restarted to know whether # we are truly finished diff --git a/snowfakery/cli.py b/snowfakery/cli.py index 17cece61..e5039b44 100755 --- a/snowfakery/cli.py +++ b/snowfakery/cli.py @@ -7,7 +7,7 @@ import click from snowfakery import version -from snowfakery.api import file_extensions, generate_data +from snowfakery.api import file_extensions, generate_data, COUNT_REPS if __name__ == "__main__": # pragma: no cover sys.path.append(str(Path(__file__).parent.parent)) @@ -77,10 +77,17 @@ def int_string_tuple(ctx, param, value=None): ) @click.option( "--target-number", + "--target-count", nargs=2, - help="Target options for the recipe YAML in the form of 'number tablename'. For example: '50 Account'.", + help="Target record count for the recipe YAML in the form of 'number tablename'. " + "For example: '50 Account' to generate roughly 50 accounts.", callback=int_string_tuple, # noqa https://github.com/pallets/click/issues/789#issuecomment-535121714 ) +@click.option( + "--reps", + help="Target repetition count for the recipe YAML. Use as an alternative to --target-number", + type=int, +) @click.option( "--debug-internals/--no-debug-internals", "debug_internals", default=False ) @@ -125,6 +132,7 @@ def generate_cli( option=(), dburls=(), target_number=None, + reps=None, debug_internals=None, generate_cci_mapping_file=None, output_format=None, @@ -163,10 +171,15 @@ def generate_cli( output_format, output_files, output_folder, + target_number, + reps, ) try: user_options = dict(option) plugin_options = dict(plugin_option) + if reps: + target_number = (COUNT_REPS, reps) + generate_data( yaml_file=yaml_file, user_options=user_options, @@ -201,6 +214,8 @@ def validate_options( output_format, output_files, output_folder, + target_number, + reps, ): if dburl and output_format: raise click.ClickException( @@ -221,6 +236,12 @@ def validate_options( "--output-folder can only be used with --output-file= or --output-format=csv" ) + if target_number and reps: + raise click.ClickException( + "Sorry, you need to pick --target_number or --reps " + "because they are mutually exclusive." + ) + def main(): generate_cli.main(prog_name="snowfakery") diff --git a/tests/test_cli.py b/tests/test_cli.py index 29e9d217..43bd9b53 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -179,6 +179,12 @@ def test_from_cli__target_number(self, capsys): assert len(re.findall(r"Account\(", stdout)) == 5 + def test_from_cli__reps(self, capsys): + generate_cli.main([str(sample_yaml), "--reps", "3"], standalone_mode=False) + stdout = capsys.readouterr().out + + assert len(re.findall(r"Account\(", stdout)) == 3 + def test_from_cli__explicit_format_txt(self, capsys): with named_temporary_file_path() as t: generate_cli.main( From 885a13cd04fde0bea03fa3a61925f3b161c35776 Mon Sep 17 00:00:00 2001 From: Paul Prescod Date: Tue, 15 Jun 2021 10:35:36 -0700 Subject: [PATCH 21/53] Docs --- docs/index.md | 41 ++++++++++++++++++++++++++++++++++------- 1 file changed, 34 insertions(+), 7 deletions(-) diff --git a/docs/index.md b/docs/index.md index b1293ba1..a26de230 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1071,13 +1071,21 @@ Options: sqlite:///foo.db if you don't have one set up. - --output-format [JSON|json|txt|csv|sql|PNG|png|SVG|svg|svgz|jpeg|jpg|ps|dot] + --output-format [png|svg|svgz|jpeg|jpg|ps|dot|json|txt|csv|sql] --output-folder PATH -o, --output-file PATH - --option EVAL_ARG... Options to send to the recipe YAML. - --target-number TEXT... Target options for the recipe YAML in the - form of 'number tablename'. For example: '50 - Account'. + --option EVAL_ARG... Option to send to the recipe YAML in a + format like 'OptName OptValue'. Specify + multiple times if needed. + + --target-number, --target-count TEXT... + Target record count for the recipe YAML in + the form of 'number tablename'. For example: + '50 Account' to generate roughly 50 + accounts. + + --reps INTEGER Target repetition count for the recipe YAML. + Use as an alternative to --target-number --debug-internals / --no-debug-internals --generate-cci-mapping-file FILENAME @@ -1092,6 +1100,10 @@ Options: --continuation-file FILENAME Continue generating a dataset where 'continuation-file' left off + --plugin-option EVAL_ARG... Option to send to a plugin in a format like + 'OptName OptValue'. Specify multiple times + if needed. + --load-declarations FILE Declarations to mix into the generated mapping file @@ -1101,7 +1113,23 @@ Options: ### Scaling up recipe execution -From the command line you can control how many rows a recipe generates. You do this by specifying a "target count" and a "target tablename", like this: +From the command line you can control how many rows a recipe generates. + +The simple way is: + +```s +snowfakery accounts.yml --reps 1000 +``` + +This will run the recipe 1000 times. Easy! + +But consider if the user wants to run a test against roughly 50,000 accounts. They +could do a calculation to figure out how many reps, but this may be complex +because Snowfakery has randomization features, so that a recipe might generate +a random number of accounts in each run. Even for simpler recipes, doing the +math may be a headache, especially if you are changing the recipe every day. + +A better solution is to specify the"target count" and a "target tablename", like this: ```s snowfakery accounts.yml --target-number 1000 Account @@ -1146,7 +1174,6 @@ for all of the CSV files. ## Advanced Features - ### Singletons with the "just_once" feature Snowfakery scales up to larger data volumes From 5b0b1fa2884df05dc862a8052a762d4a7bfc1563 Mon Sep 17 00:00:00 2001 From: Paul Prescod Date: Tue, 15 Jun 2021 11:52:40 -0700 Subject: [PATCH 22/53] Remove \n --- tools/faker_docs_utils/fakedata_header_short.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/faker_docs_utils/fakedata_header_short.md b/tools/faker_docs_utils/fakedata_header_short.md index d4960e90..ea92c8c9 100644 --- a/tools/faker_docs_utils/fakedata_header_short.md +++ b/tools/faker_docs_utils/fakedata_header_short.md @@ -1,4 +1,4 @@ -# Fake Data: {locale}\n +# Fake Data: {locale} The basic concepts of fake data are described in the [main tutorial](../fakedata.md#fake-data). @@ -7,4 +7,4 @@ Our fake data can be localized to many languages. We have [detailed docs](https://snowfakery.readthedocs.io/en/feature-fake-data-docs/locales.html) about the other languages. -Current Locale: {locale} ({current_country})\n +Current Locale: {locale} ({current_country}) From 4a994030f4dea08042db0b5a3e9a31c65d51c30e Mon Sep 17 00:00:00 2001 From: Paul Prescod Date: Tue, 15 Jun 2021 13:23:44 -0700 Subject: [PATCH 23/53] Change the sample doc template --- tools/faker_docs_utils/format_samples.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/faker_docs_utils/format_samples.py b/tools/faker_docs_utils/format_samples.py index 1efd1947..1dec13f6 100644 --- a/tools/faker_docs_utils/format_samples.py +++ b/tools/faker_docs_utils/format_samples.py @@ -82,10 +82,10 @@ def yaml_sample(name, kwds, kw_example, locale): inline_example = f'"{inline_example}"' yaml_data = f""" - - object: Example + - object: SomeObject fields: - inline_example: {inline_example} - block_example: {block_example}""" + formula_field_example: {inline_example} + block_field_example: {block_example}""" if locale: locale_decl = f""" From 25e09fbf3383f85f7cb215b81ff6ab8b37727e8e Mon Sep 17 00:00:00 2001 From: Paul Prescod Date: Tue, 15 Jun 2021 15:53:09 -0700 Subject: [PATCH 24/53] Samples overrides and CI --- .github/workflows/ci.yml | 17 ++ docs/salesforce.md | 8 +- snowfakery/fakedata/fake_data_generator.py | 2 +- tools/faker_docs_utils/docs_config.yml | 227 ++++++++++++++++++--- tools/faker_docs_utils/faker_markdown.py | 14 +- tools/faker_docs_utils/format_samples.py | 4 + tools/faker_docs_utils/summarize_fakers.py | 16 +- 7 files changed, 250 insertions(+), 38 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a4b7e5e1..c79a361e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -55,6 +55,23 @@ jobs: - name: Run Tests run: python -m pytest + faker_docs: + name: Faker Docs + runs-on: ubuntu-latest + steps: + - uses: "actions/checkout@v2" + - uses: "actions/setup-python@v1" + with: + python-version: "3.9" + + - name: Install dependencies + run: | + python -VV + python -m pip install --upgrade pip pip-tools + make dev-install + python setup.py install + make docs + windows: name: Windows ${{ matrix.python-version }} runs-on: windows-latest diff --git a/docs/salesforce.md b/docs/salesforce.md index 7905d605..081bec87 100644 --- a/docs/salesforce.md +++ b/docs/salesforce.md @@ -262,13 +262,13 @@ You can use Person Accounts like this: - object: Account fields: FirstName: - fake: first_name + fake: FirstName LastName: - fake: last_name + fake: LastName PersonMailingStreet: - fake: street_address + fake: StreetAddress PersonMailingCity: - fake: city + fake: City PersonContactId: Salesforce.SpecialObject: PersonContact ``` diff --git a/snowfakery/fakedata/fake_data_generator.py b/snowfakery/fakedata/fake_data_generator.py index 6ee72ad6..066f1137 100644 --- a/snowfakery/fakedata/fake_data_generator.py +++ b/snowfakery/fakedata/fake_data_generator.py @@ -31,7 +31,7 @@ def state(self): return self.f.administrative_unit() def postalcode(self): - """Return watever counts as a postalcode for a particular locale""" + """Return whatever counts as a postalcode for a particular locale""" return self.f.postcode() diff --git a/tools/faker_docs_utils/docs_config.yml b/tools/faker_docs_utils/docs_config.yml index 9d37c936..b88b5c5b 100644 --- a/tools/faker_docs_utils/docs_config.yml +++ b/tools/faker_docs_utils/docs_config.yml @@ -1,29 +1,200 @@ common_fakes: - - company - - name - - name_female - - name_male - - last_name - - first_name - - first_name_female - - first_name_male - - first_name_nonbinary - - catch_phrase - - year - - email - - phone_number - - building_number - - city - - state - - postalcode - - administrative_unit - - street_address - - country - - country_code - - current_country - - current_country_code - - time - - paragraph - - word - - sentence - - text + company: + example: + - object: Account + fields: + Name: + fake: Company + - object: Account + fields: + Name: ${{fake.Company}} Holdings + last_name: + example: + - object: Contact + fields: + FirstName: + fake: FirstName + LastName: + fake: LastName + - object: Contact + fields: + FirstName: ${{fake.FirstName}} Sam + LastName: ${{fake.FirstName}} Senior + first_name: + example: + - object: Contact + fields: + FirstName: + fake: FirstName + LastName: + fake: LastName + - object: Contact + fields: + FirstName: ${{fake.FirstName}} Sam + LastName: ${{fake.LastName}}-Jones + first_name_female: + example: + - object: Contact + fields: + FirstName: + fake: FirstNameFemale + LastName: + fake: LastName + - object: Contact + fields: + FirstName: ${{fake.FirstNameFemale}} Beth + LastName: ${{fake.LastNameLastName}}-Jones + first_name_male: + example: + - object: Contact + fields: + FirstName: + fake: FirstNameMale + LastName: + fake: LastName + - object: Contact + fields: + FirstName: ${{fake.FirstNameMale}} Beth + LastName: ${{fake.LastName}}-Jones + first_name_nonbinary: + example: + - object: Contact + fields: + FirstName: + fake: FirstNameNonBinary + LastName: + fake: LastName + - object: Contact + fields: + FirstName: ${{fake.FirstNameNonBinary}} Mary-John + LastName: ${{fake.LastName}}-Jones + catch_phrase: + example: + - object: Account + fields: + Name: + fake: Company + Description: + fake: CatchPhrase + - object: Account + fields: + Name: + Name: ${{fake.Company}} Holdings + Description: "Our Motto: ${{fake.CatchPhrase}}" + year: + example: + - object: Student + fields: + GraduationYear: + fake: year + - object: Student + fields: + GraduationYear: ${{year}} + email: + example: + - object: Contact + fields: + FirstName: + fake: FirstName + LastName: + fake: LastName + Email: + fake: Email + - object: Contact + fields: + FirstName: ${{fake.FirstName}} Sam + LastName: ${{fake.FirstName}} Senior + Email: ${{fake.Email}} + phone_number: + example: + - object: Account + fields: + Name: + fake: Company + Phone: + fake: PhoneNumber + - object: Account + fields: + Name: ${{fake.Company}} Holdings + Phone: ${{fake.PhoneNumber}} ext. 23 + city: + example: + - object: Account + fields: + Name: + fake: Company + BillingCity: + fake: City + - object: Account + fields: + Name: ${{fake.Company}} Holdings + BillingCity: ${{fake.City}} + state: + example: + - object: Account + fields: + Name: + fake: Company + BillingState: + fake: State + - object: Account + fields: + Name: ${{fake.Company}} Holdings + BillingState: ${{fake.State}} + postalcode: + example: + - object: Account + fields: + Name: + fake: Company + BillingPostalCode: + fake: postalcode + - object: Account + fields: + Name: ${{fake.Company}} Holdings + BillingPostalCode: ${{fake.Postalcode}} + street_address: + example: + - object: Account + fields: + Name: + fake: Company + BillingStreet: + fake: StreetAddress + - object: Account + fields: + Name: ${{fake.Company}} Holdings + BillingStreet: ${{fake.StreetAddress}} + country: + example: + - object: Account + fields: + Name: + fake: Company + BillingStreet: + fake: Country + - object: Account + fields: + Name: ${{fake.Company}} Holdings + BillingStreet: ${{fake.Country}} + current_country: + example: + - object: Account + fields: + Name: + fake: Company + BillingStreet: + fake: CurrentCountry + - object: Account + fields: + Name: ${{fake.Company}} Holdings + BillingStreet: ${{fake.CurrentCountry}} + time: + paragraph: + word: + sentence: + text: +uncommon_fakes: + building_number: + country_code: + current_country_code: diff --git a/tools/faker_docs_utils/faker_markdown.py b/tools/faker_docs_utils/faker_markdown.py index 8c93532c..9a58a549 100644 --- a/tools/faker_docs_utils/faker_markdown.py +++ b/tools/faker_docs_utils/faker_markdown.py @@ -2,9 +2,13 @@ from functools import lru_cache from pathlib import Path +from yaml import dump as yaml_dump from faker import Faker from faker.config import AVAILABLE_LOCALES -from tools.faker_docs_utils.format_samples import yaml_samples_for_docstring +from tools.faker_docs_utils.format_samples import ( + yaml_samples_for_docstring, + snowfakery_output_for, +) from tools.faker_docs_utils.summarize_fakers import get_all_fakers from snowfakery.fakedata.fake_data_generator import FakeData @@ -98,8 +102,12 @@ def output_faker(name, data, output, locale): output() link = f"[{data.source}]({data.url})" output("Source:", link) - samples = yaml_samples_for_docstring(name, data.fullname, data.doc, locale) - samples = list(filter(None, samples)) + if data.sample: + example = yaml_dump(data.sample, sort_keys=False) + samples = [snowfakery_output_for(example)] + else: + samples = yaml_samples_for_docstring(name, data.fullname, data.doc, locale) + samples = list(filter(None, samples)) if samples: output() for sample in samples: diff --git a/tools/faker_docs_utils/format_samples.py b/tools/faker_docs_utils/format_samples.py index 1dec13f6..a9f42c27 100644 --- a/tools/faker_docs_utils/format_samples.py +++ b/tools/faker_docs_utils/format_samples.py @@ -101,6 +101,10 @@ def yaml_sample(name, kwds, kw_example, locale): print(str(e)[0:100]) raise + return snowfakery_output_for(yaml_data) + + +def snowfakery_output_for(yaml_data): with StringIO() as s: try: generate_data(StringIO(yaml_data), output_file=s, output_format="txt") diff --git a/tools/faker_docs_utils/summarize_fakers.py b/tools/faker_docs_utils/summarize_fakers.py index 2292040e..0f906ab7 100644 --- a/tools/faker_docs_utils/summarize_fakers.py +++ b/tools/faker_docs_utils/summarize_fakers.py @@ -9,7 +9,9 @@ def get_all_fakers(faker): from snowfakery.utils.collections import CaseInsensitiveDict with (Path(__file__).parent / "docs_config.yml").open() as f: - common_fakes = yaml.safe_load(f)["common_fakes"] + yaml_data = yaml.safe_load(f) + common_fakes = yaml_data["common_fakes"] + uncommon_fakes = yaml_data["uncommon_fakes"] faker_infos = CaseInsensitiveDict() for name, meth in faker.fake_names.items(): @@ -21,6 +23,7 @@ def get_all_fakers(faker): filename = func.__code__.co_filename cls = meth.__self__.__class__ fullname = cls.__module__ + "." + cls.__name__ + "." + meth.__name__ + overrides = common_fakes.get(meth.__name__) or uncommon_fakes.get(meth.__name__) is_common = meth.__name__ in common_fakes if "/faker/" in filename: source = "faker" @@ -41,7 +44,15 @@ def get_all_fakers(faker): faker_info = faker_infos.setdefault( friendly, FakerInfo( - friendly, fullname, [], url, source, category, doc or "", is_common + friendly, + fullname, + [], + url, + source, + category, + doc or "", + is_common, + overrides.get("example") if overrides else None, ), ) faker_info.aliases.append(name) @@ -58,6 +69,7 @@ class FakerInfo(T.NamedTuple): category: str doc: str common: bool + sample: str def _to_camel_case(snake_str): From 1140bfd519fd112b8e437285110546f04a017689 Mon Sep 17 00:00:00 2001 From: Paul Prescod Date: Tue, 15 Jun 2021 16:43:46 -0700 Subject: [PATCH 25/53] Fix typos --- .github/workflows/ci.yml | 4 +++- tools/faker_docs_utils/docs_config.yml | 3 +-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c79a361e..ff069356 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -70,7 +70,9 @@ jobs: python -m pip install --upgrade pip pip-tools make dev-install python setup.py install - make docs + + - name: Make Docs + run: make docs windows: name: Windows ${{ matrix.python-version }} diff --git a/tools/faker_docs_utils/docs_config.yml b/tools/faker_docs_utils/docs_config.yml index b88b5c5b..273a1ff2 100644 --- a/tools/faker_docs_utils/docs_config.yml +++ b/tools/faker_docs_utils/docs_config.yml @@ -78,8 +78,7 @@ common_fakes: fake: CatchPhrase - object: Account fields: - Name: - Name: ${{fake.Company}} Holdings + Name: ${{fake.Company}} Holdings Description: "Our Motto: ${{fake.CatchPhrase}}" year: example: From f7e85e6a17a48b9da2f89baff276572e08248006 Mon Sep 17 00:00:00 2001 From: Paul Prescod Date: Wed, 16 Jun 2021 14:55:38 -0700 Subject: [PATCH 26/53] Add dev-installation instruction --- CONTRIBUTING.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index 2efa523d..c53db846 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -72,7 +72,8 @@ Or you could make it outside of the project repo. $ pytest Test the documentation like this: - + + $ pip install -e . $ make docs $ open build/html/index.html From d6f70f5b5118f0662403ebd9aba2e0d6587c412e Mon Sep 17 00:00:00 2001 From: Paul Prescod Date: Thu, 17 Jun 2021 07:26:24 -0700 Subject: [PATCH 27/53] Attempt to fix locales --- Makefile | 1 + tools/faker_docs_utils/faker_markdown.py | 7 ++++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 66c47281..2798d6f3 100644 --- a/Makefile +++ b/Makefile @@ -4,6 +4,7 @@ update-deps: dev-install: pip-sync requirements/*.txt + pip install -e . # set SF_MKDOCS_BUILD_LOCALES=False to skip building all locales docs: .FORCE diff --git a/tools/faker_docs_utils/faker_markdown.py b/tools/faker_docs_utils/faker_markdown.py index 9a58a549..ffb11c46 100644 --- a/tools/faker_docs_utils/faker_markdown.py +++ b/tools/faker_docs_utils/faker_markdown.py @@ -103,7 +103,12 @@ def output_faker(name, data, output, locale): link = f"[{data.source}]({data.url})" output("Source:", link) if data.sample: - example = yaml_dump(data.sample, sort_keys=False) + if locale and locale != "en_US": + locale_header = [{"var": "snowfakery_locale", "value": locale}] + sample = locale_header + data.sample + else: + sample = data.sample + example = yaml_dump(sample, sort_keys=False) samples = [snowfakery_output_for(example)] else: samples = yaml_samples_for_docstring(name, data.fullname, data.doc, locale) From ebfb3761a281712a6d55167f65a39e5c7a4b6f2c Mon Sep 17 00:00:00 2001 From: Paul Prescod Date: Thu, 17 Jun 2021 07:53:45 -0700 Subject: [PATCH 28/53] Temp workaround for docs --- tools/faker_docs_utils/faker_markdown.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tools/faker_docs_utils/faker_markdown.py b/tools/faker_docs_utils/faker_markdown.py index ffb11c46..c7d7c79b 100644 --- a/tools/faker_docs_utils/faker_markdown.py +++ b/tools/faker_docs_utils/faker_markdown.py @@ -116,7 +116,11 @@ def output_faker(name, data, output, locale): if samples: output() for sample in samples: - yaml, out = sample + try: + yaml, out = sample + except: # FIXME!!!! + continue + output("Recipe:\n") output(indent(yaml)) output("Outputs:\n") From 1f72b216754a60a711bcd6a402670f871679b623 Mon Sep 17 00:00:00 2001 From: Paul Prescod Date: Thu, 17 Jun 2021 08:05:52 -0700 Subject: [PATCH 29/53] Undo hack --- tools/faker_docs_utils/faker_markdown.py | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/tools/faker_docs_utils/faker_markdown.py b/tools/faker_docs_utils/faker_markdown.py index c7d7c79b..b31e5f0e 100644 --- a/tools/faker_docs_utils/faker_markdown.py +++ b/tools/faker_docs_utils/faker_markdown.py @@ -112,14 +112,11 @@ def output_faker(name, data, output, locale): samples = [snowfakery_output_for(example)] else: samples = yaml_samples_for_docstring(name, data.fullname, data.doc, locale) - samples = list(filter(None, samples)) + samples = list(filter(None, samples)) if samples: output() for sample in samples: - try: - yaml, out = sample - except: # FIXME!!!! - continue + yaml, out = sample output("Recipe:\n") output(indent(yaml)) From a8fe7ba74d7dd75560da743700dc0470ec3c1e77 Mon Sep 17 00:00:00 2001 From: Paul Prescod Date: Thu, 17 Jun 2021 13:44:06 -0700 Subject: [PATCH 30/53] Cleanup warnings and output --- tools/faker_docs_utils/faker_markdown.py | 36 ++++++++++++------- tools/faker_docs_utils/format_samples.py | 19 ++++++---- .../mkdocs_plugins/main_mkdocs_plugin.py | 4 +-- 3 files changed, 38 insertions(+), 21 deletions(-) diff --git a/tools/faker_docs_utils/faker_markdown.py b/tools/faker_docs_utils/faker_markdown.py index b31e5f0e..10e290cb 100644 --- a/tools/faker_docs_utils/faker_markdown.py +++ b/tools/faker_docs_utils/faker_markdown.py @@ -92,16 +92,7 @@ def categorize(fakers): return {name: value for name, value in sorted(categories.items())} -def output_faker(name, data, output, locale): - output(f"#### fake: {name}\n") - if strip(data.doc): - output(strip(data.doc)) - output() - - output("Aliases: ", ", ".join(data.aliases)) - output() - link = f"[{data.source}]({data.url})" - output("Source:", link) +def gather_samples(name, data, locale): if data.sample: if locale and locale != "en_US": locale_header = [{"var": "snowfakery_locale", "value": locale}] @@ -109,10 +100,28 @@ def output_faker(name, data, output, locale): else: sample = data.sample example = yaml_dump(sample, sort_keys=False) - samples = [snowfakery_output_for(example)] + samples = [snowfakery_output_for(data.name, example)] else: samples = yaml_samples_for_docstring(name, data.fullname, data.doc, locale) samples = list(filter(None, samples)) + + +def output_faker(name: str, data: str, output: callable, locale: str): + samples = gather_samples(name, data, locale) + # if there isn't at least one sample, don't publish + if not samples: + return + + output(f"#### fake: {name}\n") + if strip(data.doc): + output(strip(data.doc)) + output() + + output("Aliases: ", ", ".join(data.aliases)) + output() + link = f"[{data.source}]({data.url})" + output("Source:", link) + if samples: output() for sample in samples: @@ -150,5 +159,8 @@ def output(*args, **kwargs): locales = locales_as_markdown(None) if locales: - output("## Faker Locales\n") + output("## Fake Data Locales\n") + output( + "Learn more about Snowfakery localization in the [Fake Data Tutorial](fakedata.md#localization)\n" + ) output(locales) diff --git a/tools/faker_docs_utils/format_samples.py b/tools/faker_docs_utils/format_samples.py index a9f42c27..0df7799d 100644 --- a/tools/faker_docs_utils/format_samples.py +++ b/tools/faker_docs_utils/format_samples.py @@ -9,6 +9,8 @@ from . import docstring +ALREADY_GENERATED_ERROR_FOR = set() + def samples_from_docstring(fullname, docstring_data): lines = docstring_data.split("\n") @@ -61,7 +63,9 @@ def yaml_samples_for_docstring_sample_inner(name, sample, locale): try: kwds = extract_keywords(sample.kwargs) except Exception as e: - print("Cannot extract keywords", sample, str(e)[0:100]) + if name not in ALREADY_GENERATED_ERROR_FOR: + ALREADY_GENERATED_ERROR_FOR.add(name) + print("Cannot extract keywords", sample, str(e)[0:100]) return None name = name.split(".")[-1] @@ -101,17 +105,20 @@ def yaml_sample(name, kwds, kw_example, locale): print(str(e)[0:100]) raise - return snowfakery_output_for(yaml_data) + return snowfakery_output_for(name, yaml_data) -def snowfakery_output_for(yaml_data): +def snowfakery_output_for(name, yaml_data): with StringIO() as s: try: generate_data(StringIO(yaml_data), output_file=s, output_format="txt") except Exception as e: - print("Cannot generate") - print(yaml_data) - print(str(e)[0:100]) + if name not in ALREADY_GENERATED_ERROR_FOR: + print(f"Cannot generate sample for {name}: {str(e)[0:50]}") + ALREADY_GENERATED_ERROR_FOR.add(name) + + # print(yaml_data) + # print(str(e)[0:100]) output = s.getvalue() if output: return yaml_data, output diff --git a/tools/faker_docs_utils/mkdocs_plugins/main_mkdocs_plugin.py b/tools/faker_docs_utils/mkdocs_plugins/main_mkdocs_plugin.py index 066d61da..9132da2d 100644 --- a/tools/faker_docs_utils/mkdocs_plugins/main_mkdocs_plugin.py +++ b/tools/faker_docs_utils/mkdocs_plugins/main_mkdocs_plugin.py @@ -28,9 +28,7 @@ def on_pre_build(self, config): lru_cache(maxsize=10_000)(Factory._get_provider_class), ) - with sys_path_patch, lru_patch, open(os.devnull, "w") as devnull, patch.object( - sys, "stdout", devnull - ): + with sys_path_patch, lru_patch: from tools.faker_docs_utils.faker_markdown import ( generate_markdown_for_all_locales, generate_markdown_for_fakers, From 5063f2b5777f834bd4aa202587c9a1e8359eaf90 Mon Sep 17 00:00:00 2001 From: Paul Prescod Date: Thu, 17 Jun 2021 14:58:13 -0700 Subject: [PATCH 31/53] Fix samples --- CONTRIBUTING.rst | 8 ++++---- mkdocs.yml | 1 + tools/faker_docs_utils/docs_config.yml | 2 +- tools/faker_docs_utils/docstring.py | 11 ++++------- tools/faker_docs_utils/faker_markdown.py | 3 ++- .../mkdocs_plugins/main_mkdocs_plugin.py | 14 +++++++++++++- 6 files changed, 25 insertions(+), 14 deletions(-) diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index c53db846..bc5f8ad7 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -71,13 +71,13 @@ Or you could make it outside of the project repo. $ pytest - Test the documentation like this: - - $ pip install -e . +7. Build the docs like this: $ make docs $ open build/html/index.html -7. Your new code should also have meaningful tests. One way to double check that +Set SF_MKDOCS_BUILD_LOCALES=False to skip building all locales + +8. Your new code should also have meaningful tests. One way to double check that your tests cover everything is to ensure that your new code has test code coverage: $ pytest --cov diff --git a/mkdocs.yml b/mkdocs.yml index 9a7b5571..09ab2232 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -7,6 +7,7 @@ nav: - index.md - salesforce.md - Fake Data: fakedata.md + - Localization: locales.md - embedding.md - extending.md extra_css: diff --git a/tools/faker_docs_utils/docs_config.yml b/tools/faker_docs_utils/docs_config.yml index 273a1ff2..56abc85f 100644 --- a/tools/faker_docs_utils/docs_config.yml +++ b/tools/faker_docs_utils/docs_config.yml @@ -43,7 +43,7 @@ common_fakes: - object: Contact fields: FirstName: ${{fake.FirstNameFemale}} Beth - LastName: ${{fake.LastNameLastName}}-Jones + LastName: ${{fake.LastName}}-Jones first_name_male: example: - object: Contact diff --git a/tools/faker_docs_utils/docstring.py b/tools/faker_docs_utils/docstring.py index 304352c4..db48dddc 100644 --- a/tools/faker_docs_utils/docstring.py +++ b/tools/faker_docs_utils/docstring.py @@ -1,6 +1,8 @@ # Based on https://github.com/joke2k/faker/blob/2dac486e6d3b5f018feb524f6fa19917ec10299e/faker/sphinx/docstring.py # Copied under the provisions of the MIT License +# Search for "snowfakery" to find optimizations we've made. + # coding=utf-8 import inspect import logging @@ -198,7 +200,6 @@ def _generate_samples(self): self._inject_default_sample_section() output = "" - eval_scope = self._generate_eval_scope() for sample in self._samples: command = _command_template.format( method=self._method, kwargs=sample.kwargs @@ -214,12 +215,8 @@ def _generate_samples(self): try: Faker.seed(sample.seed) - results = "\n".join( - [ - self._stringify_result(eval(command, eval_scope)) - for _ in range(sample.size) - ] - ) + # optimization for the Snowfakery context + results = "" except Exception as e: msg = f"Sample generation failed for method `{self._method}` with arguments `{sample.kwargs}`: {e}." self._log_warning(msg) diff --git a/tools/faker_docs_utils/faker_markdown.py b/tools/faker_docs_utils/faker_markdown.py index 10e290cb..f7c4c933 100644 --- a/tools/faker_docs_utils/faker_markdown.py +++ b/tools/faker_docs_utils/faker_markdown.py @@ -103,7 +103,7 @@ def gather_samples(name, data, locale): samples = [snowfakery_output_for(data.name, example)] else: samples = yaml_samples_for_docstring(name, data.fullname, data.doc, locale) - samples = list(filter(None, samples)) + return list(filter(None, samples)) def output_faker(name: str, data: str, output: callable, locale: str): @@ -148,6 +148,7 @@ def prefix(line): def generate_markdown_for_all_locales(path: Path, locales=AVAILABLE_LOCALES): for locale in locales: with Path(path, f"{locale}.md").open("w") as f: + print(f.name) generate_markdown_for_fakers(f, locale) diff --git a/tools/faker_docs_utils/mkdocs_plugins/main_mkdocs_plugin.py b/tools/faker_docs_utils/mkdocs_plugins/main_mkdocs_plugin.py index 9132da2d..77710b8a 100644 --- a/tools/faker_docs_utils/mkdocs_plugins/main_mkdocs_plugin.py +++ b/tools/faker_docs_utils/mkdocs_plugins/main_mkdocs_plugin.py @@ -3,6 +3,7 @@ import os from unittest.mock import patch from functools import lru_cache +from logging import Logger from mkdocs.plugins import BasePlugin from faker.factory import Factory @@ -21,6 +22,17 @@ def on_pre_build(self, config): # make modules available sys_path_patch = patch.object(sys, "path", new_sys_path) + warning = Logger.warning + + irritating_warning = "Numbers generated by this method are purely hypothetical." + + def new_warning(self, *args, **kwargs): + if args == (irritating_warning,): + return + else: + warning(self, *args, **kwargs) + + logger_patch = patch("logging.Logger.warning", new=new_warning) # speed up a critical function lru_patch = patch( @@ -28,7 +40,7 @@ def on_pre_build(self, config): lru_cache(maxsize=10_000)(Factory._get_provider_class), ) - with sys_path_patch, lru_patch: + with sys_path_patch, lru_patch, logger_patch: from tools.faker_docs_utils.faker_markdown import ( generate_markdown_for_all_locales, generate_markdown_for_fakers, From 1a5f46ae85de67181d06df66aa51da6ba1f392e6 Mon Sep 17 00:00:00 2001 From: Paul Prescod Date: Thu, 17 Jun 2021 19:13:02 -0700 Subject: [PATCH 32/53] Fix typos --- tools/faker_docs_utils/docs_config.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tools/faker_docs_utils/docs_config.yml b/tools/faker_docs_utils/docs_config.yml index 56abc85f..23f60a6d 100644 --- a/tools/faker_docs_utils/docs_config.yml +++ b/tools/faker_docs_utils/docs_config.yml @@ -170,24 +170,24 @@ common_fakes: fields: Name: fake: Company - BillingStreet: + BillingCountry: fake: Country - object: Account fields: Name: ${{fake.Company}} Holdings - BillingStreet: ${{fake.Country}} + BillingCountry: ${{fake.Country}} current_country: example: - object: Account fields: Name: fake: Company - BillingStreet: + BillingCountry: fake: CurrentCountry - object: Account fields: Name: ${{fake.Company}} Holdings - BillingStreet: ${{fake.CurrentCountry}} + BillingCountry: ${{fake.CurrentCountry}} time: paragraph: word: From 6c6a1c82fb473ad29168a4fd686ae9e3d8b5c175 Mon Sep 17 00:00:00 2001 From: Paul Prescod Date: Thu, 17 Jun 2021 20:27:20 -0700 Subject: [PATCH 33/53] Clean up language names --- .../faker_docs_utils/fakedata_header_short.md | 2 +- tools/faker_docs_utils/faker_markdown.py | 14 +- tools/faker_docs_utils/language_codes.py | 190 ++++++++++++++++++ 3 files changed, 202 insertions(+), 4 deletions(-) create mode 100644 tools/faker_docs_utils/language_codes.py diff --git a/tools/faker_docs_utils/fakedata_header_short.md b/tools/faker_docs_utils/fakedata_header_short.md index ea92c8c9..a68c3427 100644 --- a/tools/faker_docs_utils/fakedata_header_short.md +++ b/tools/faker_docs_utils/fakedata_header_short.md @@ -1,4 +1,4 @@ -# Fake Data: {locale} +# Fake Data: {language} as spoken in {current_country} ({locale}) The basic concepts of fake data are described in the [main tutorial](../fakedata.md#fake-data). diff --git a/tools/faker_docs_utils/faker_markdown.py b/tools/faker_docs_utils/faker_markdown.py index f7c4c933..a02e16ca 100644 --- a/tools/faker_docs_utils/faker_markdown.py +++ b/tools/faker_docs_utils/faker_markdown.py @@ -9,7 +9,8 @@ yaml_samples_for_docstring, snowfakery_output_for, ) -from tools.faker_docs_utils.summarize_fakers import get_all_fakers +from .summarize_fakers import get_all_fakers +from .language_codes import language_codes from snowfakery.fakedata.fake_data_generator import FakeData @@ -45,7 +46,8 @@ def format_link(locale: str): country_name = country_for_locale(locale) except (ValueError, AttributeError): return None - link_text = f"{locale} : {country_name}" + language = language_codes[locale.split("_")[0]] + link_text = f"{language} as spoken in {country_name}: ({locale})" return f" - [{link_text}](fakedata/{locale}.md)\n" other_locales = [locale for locale in AVAILABLE_LOCALES if locale != current_locale] @@ -58,6 +60,7 @@ def format_link(locale: str): def generate_markdown_for_fakers(outfile, locale: str, header: str = standard_header): faker = Faker(locale) + language = language_codes[locale.split("_")[0]] fd = FakeData(faker) all_fakers = get_all_fakers(fd) @@ -65,7 +68,12 @@ def generate_markdown_for_fakers(outfile, locale: str, header: str = standard_he def output(*args, **kwargs): print(*args, **kwargs, file=outfile) - output(header.format(locale=locale, current_country=faker.current_country())) + head_md = header.format( + locale=locale, current_country=faker.current_country(), language=language + ) + output( + head_md, + ) output("[TOC]\n") diff --git a/tools/faker_docs_utils/language_codes.py b/tools/faker_docs_utils/language_codes.py new file mode 100644 index 00000000..2eda9969 --- /dev/null +++ b/tools/faker_docs_utils/language_codes.py @@ -0,0 +1,190 @@ +language_codes = dict( + ( + ("ab", "Abkhaz"), + ("aa", "Afar"), + ("af", "Afrikaans"), + ("ak", "Akan"), + ("sq", "Albanian"), + ("am", "Amharic"), + ("ar", "Arabic"), + ("an", "Aragonese"), + ("hy", "Armenian"), + ("as", "Assamese"), + ("av", "Avaric"), + ("ae", "Avestan"), + ("ay", "Aymara"), + ("az", "Azerbaijani"), + ("bm", "Bambara"), + ("ba", "Bashkir"), + ("eu", "Basque"), + ("be", "Belarusian"), + ("bn", "Bengali"), + ("bh", "Bihari"), + ("bi", "Bislama"), + ("bs", "Bosnian"), + ("br", "Breton"), + ("bg", "Bulgarian"), + ("my", "Burmese"), + ("ca", "Catalan; Valencian"), + ("ch", "Chamorro"), + ("ce", "Chechen"), + ("ny", "Chichewa; Chewa; Nyanja"), + ("zh", "Chinese"), + ("cv", "Chuvash"), + ("kw", "Cornish"), + ("co", "Corsican"), + ("cr", "Cree"), + ("hr", "Croatian"), + ("cs", "Czech"), + ("da", "Danish"), + ("dk", "Danish"), # wrong + ("dv", "Divehi; Maldivian;"), + ("nl", "Dutch"), + ("dz", "Dzongkha"), + ("en", "English"), + ("eo", "Esperanto"), + ("et", "Estonian"), + ("ee", "Ewe"), + ("fo", "Faroese"), + ("fj", "Fijian"), + ("fi", "Finnish"), + ("fr", "French"), + ("ff", "Fula"), + ("gl", "Galician"), + ("ka", "Georgian"), + ("de", "German"), + ("el", "Greek, Modern"), + ("gn", "Guaraní"), + ("gu", "Gujarati"), + ("ht", "Haitian"), + ("ha", "Hausa"), + ("he", "Hebrew (modern)"), + ("hz", "Herero"), + ("hi", "Hindi"), + ("ho", "Hiri Motu"), + ("hu", "Hungarian"), + ("ia", "Interlingua"), + ("id", "Indonesian"), + ("ie", "Interlingue"), + ("ga", "Irish"), + ("ig", "Igbo"), + ("ik", "Inupiaq"), + ("io", "Ido"), + ("is", "Icelandic"), + ("it", "Italian"), + ("iu", "Inuktitut"), + ("ja", "Japanese"), + ("jv", "Javanese"), + ("kl", "Kalaallisut"), + ("kn", "Kannada"), + ("kr", "Kanuri"), + ("ks", "Kashmiri"), + ("kk", "Kazakh"), + ("km", "Khmer"), + ("ki", "Kikuyu, Gikuyu"), + ("rw", "Kinyarwanda"), + ("ky", "Kirghiz, Kyrgyz"), + ("kv", "Komi"), + ("kg", "Kongo"), + ("ko", "Korean"), + ("ku", "Kurdish"), + ("kj", "Kwanyama, Kuanyama"), + ("la", "Latin"), + ("lb", "Luxembourgish"), + ("lg", "Luganda"), + ("li", "Limburgish"), + ("ln", "Lingala"), + ("lo", "Lao"), + ("lt", "Lithuanian"), + ("lu", "Luba-Katanga"), + ("lv", "Latvian"), + ("gv", "Manx"), + ("mk", "Macedonian"), + ("mg", "Malagasy"), + ("ms", "Malay"), + ("ml", "Malayalam"), + ("mt", "Maltese"), + ("mi", "Māori"), + ("mr", "Marathi (Marāṭhī)"), + ("mh", "Marshallese"), + ("mn", "Mongolian"), + ("na", "Nauru"), + ("nv", "Navajo, Navaho"), + ("nb", "Norwegian Bokmål"), + ("nd", "North Ndebele"), + ("ne", "Nepali"), + ("ng", "Ndonga"), + ("nn", "Norwegian Nynorsk"), + ("no", "Norwegian"), + ("ii", "Nuosu"), + ("nr", "South Ndebele"), + ("oc", "Occitan"), + ("oj", "Ojibwe, Ojibwa"), + ("cu", "Old Church Slavonic"), + ("om", "Oromo"), + ("or", "Oriya"), + ("os", "Ossetian, Ossetic"), + ("pa", "Panjabi, Punjabi"), + ("pi", "Pāli"), + ("fa", "Persian"), + ("fil", "Filipino"), # Not a real language code + ("pl", "Polish"), + ("ps", "Pashto, Pushto"), + ("pt", "Portuguese"), + ("qu", "Quechua"), + ("rm", "Romansh"), + ("rn", "Kirundi"), + ("ro", "Romanian, Moldavan"), + ("ru", "Russian"), + ("sa", "Sanskrit (Saṁskṛta)"), + ("sc", "Sardinian"), + ("sd", "Sindhi"), + ("se", "Northern Sami"), + ("sm", "Samoan"), + ("sg", "Sango"), + ("sr", "Serbian"), + ("gd", "Scottish Gaelic"), + ("sn", "Shona"), + ("si", "Sinhala, Sinhalese"), + ("sk", "Slovak"), + ("sl", "Slovene"), + ("so", "Somali"), + ("st", "Southern Sotho"), + ("es", "Spanish; Castilian"), + ("su", "Sundanese"), + ("sw", "Swahili"), + ("ss", "Swati"), + ("sv", "Swedish"), + ("ta", "Tamil"), + ("te", "Telugu"), + ("tg", "Tajik"), + ("th", "Thai"), + ("ti", "Tigrinya"), + ("bo", "Tibetan"), + ("tk", "Turkmen"), + ("tl", "Tagalog"), + ("tn", "Tswana"), + ("to", "Tonga"), + ("tr", "Turkish"), + ("ts", "Tsonga"), + ("tt", "Tatar"), + ("tw", "Twi"), + ("ty", "Tahitian"), + ("ug", "Uighur, Uyghur"), + ("uk", "Ukrainian"), + ("ur", "Urdu"), + ("uz", "Uzbek"), + ("ve", "Venda"), + ("vi", "Vietnamese"), + ("vo", "Volapük"), + ("wa", "Walloon"), + ("cy", "Welsh"), + ("wo", "Wolof"), + ("fy", "Western Frisian"), + ("xh", "Xhosa"), + ("yi", "Yiddish"), + ("yo", "Yoruba"), + ("za", "Zhuang, Chuang"), + ("zu", "Zulu"), + ) +) From 5ebdb39647edc51348dac799335d54de3daf6ded Mon Sep 17 00:00:00 2001 From: Paul Prescod Date: Thu, 17 Jun 2021 22:00:58 -0700 Subject: [PATCH 34/53] Clean up params and return values --- tools/faker_docs_utils/faker_markdown.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tools/faker_docs_utils/faker_markdown.py b/tools/faker_docs_utils/faker_markdown.py index a02e16ca..dfae0174 100644 --- a/tools/faker_docs_utils/faker_markdown.py +++ b/tools/faker_docs_utils/faker_markdown.py @@ -30,7 +30,9 @@ def strip(my_str): my_str = _RE_COMBINE_WHITESPACE.sub("", my_str) my_str = _RE_STRIP_SAMPLES.sub("", my_str).strip() my_str = _COMMENT_LINES_THAT_LOOK_LIKE_TITLES.sub(" #", my_str) - my_str = my_str.replace(":example", "Example:") + my_str = my_str.replace(":example", "\nExample:") + my_str = my_str.replace(":param", "\nParam:") + my_str = my_str.replace(":return", "\nReturn:") return my_str From 69d0a6e9b4986b3770db1bd9c1e0cf9273bddd59 Mon Sep 17 00:00:00 2001 From: Paul Prescod Date: Sun, 20 Jun 2021 12:28:27 -0700 Subject: [PATCH 35/53] Fix merge bug --- tests/test_with_cci.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/tests/test_with_cci.py b/tests/test_with_cci.py index e3a4045c..09eb39f7 100644 --- a/tests/test_with_cci.py +++ b/tests/test_with_cci.py @@ -115,12 +115,6 @@ def test_soql_plugin_no_query_from(self, fake_sf_client, generated_rows): with pytest.raises(DataGenError, match="Must supply 'from:'"): generate(StringIO(yaml), plugin_options={"orgname": "blah"}) - @patch( - "snowfakery.standard_plugins.Salesforce.SalesforceConnection.sf", - wraps=fake_sf_client, - ) - @patch("snowfakery.standard_plugins.Salesforce.randrange", lambda *arg, **kwargs: 5) - def test_soql_plugin_record(self, fake_sf_client, generated_rows): yaml = """ - plugin: snowfakery.standard_plugins.Salesforce.SalesforceQuery From e8dd80ea1aab5aab16a2ffa6f7a73e2d839a2195 Mon Sep 17 00:00:00 2001 From: Paul Prescod Date: Sun, 20 Jun 2021 12:30:58 -0700 Subject: [PATCH 36/53] Update gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 3623a5fc..a6e38cde 100644 --- a/.gitignore +++ b/.gitignore @@ -38,6 +38,7 @@ pip-wheel-metadata results_junit.xml test_results.json temp +coverage.xml # Salesforce / SFDX / CCI .cci From ff7d183bbdc08582382bdcb3bea13d3ae12e0dd7 Mon Sep 17 00:00:00 2001 From: Paul Prescod Date: Tue, 22 Jun 2021 11:55:15 -0700 Subject: [PATCH 37/53] Attempt to fix Windows issue --- requirements/dev.in | 3 -- requirements/dev.txt | 73 +++---------------------------------------- requirements/prod.txt | 4 +-- 3 files changed, 7 insertions(+), 73 deletions(-) diff --git a/requirements/dev.in b/requirements/dev.in index 9eb9c2b7..1365b29f 100644 --- a/requirements/dev.in +++ b/requirements/dev.in @@ -3,12 +3,9 @@ black coverage coveralls flake8 -myst-parser -pip-tools pre-commit pytest pytest-cov -Sphinx<4 # pin this until Myst is happy with Sphinx 4 typeguard==2.10.0 # do not upgrade until #181 is fixed faker-microservice tox diff --git a/requirements/dev.txt b/requirements/dev.txt index ceb84fb7..4037c805 100644 --- a/requirements/dev.txt +++ b/requirements/dev.txt @@ -4,19 +4,13 @@ # # pip-compile --allow-unsafe requirements/dev.in # -alabaster==0.7.12 - # via sphinx appdirs==1.4.4 # via # black # virtualenv attrs==21.2.0 - # via - # markdown-it-py - # pytest -babel==2.9.1 - # via sphinx -black==21.5b2 + # via pytest +black==21.6b0 # via -r requirements/dev.in certifi==2021.5.30 # via requests @@ -28,7 +22,6 @@ click==7.1.2 # via # -r requirements/prod.txt # black - # pip-tools contextvars==2.4 # via -r requirements/prod.txt coverage==5.5 @@ -42,13 +35,9 @@ distlib==0.3.2 # via virtualenv docopt==0.6.2 # via coveralls -docutils==0.16 - # via - # myst-parser - # sphinx faker-microservice==2.0.0 # via -r requirements/dev.in -faker==8.6.0 +faker==8.8.1 # via # -r requirements/prod.txt # faker-microservice @@ -70,8 +59,6 @@ idna==2.10 # via # requests # yarl -imagesize==1.2.0 - # via sphinx immutables==0.15 # via # -r requirements/prod.txt @@ -80,7 +67,6 @@ importlib-metadata==4.5.0 # via # -r requirements/prod.txt # flake8 - # pep517 # pluggy # pre-commit # pytest @@ -90,41 +76,25 @@ importlib-metadata==4.5.0 iniconfig==1.1.1 # via pytest jinja2==2.11.3 - # via - # -r requirements/prod.txt - # myst-parser - # sphinx -markdown-it-py==1.1.0 - # via - # mdit-py-plugins - # myst-parser + # via -r requirements/prod.txt markupsafe==2.0.1 # via # -r requirements/prod.txt # jinja2 mccabe==0.6.1 # via flake8 -mdit-py-plugins==0.2.8 - # via myst-parser multidict==5.1.0 # via yarl mypy-extensions==0.4.3 # via black -myst-parser==0.14.0 - # via -r requirements/dev.in nodeenv==1.6.0 # via pre-commit packaging==20.9 # via # pytest - # sphinx # tox pathspec==0.8.1 # via black -pep517==0.10.0 - # via pip-tools -pip-tools==6.1.0 - # via -r requirements/dev.in pluggy==0.13.1 # via # pytest @@ -141,8 +111,6 @@ pydantic==1.8.2 # via -r requirements/prod.txt pyflakes==2.3.1 # via flake8 -pygments==2.9.0 - # via sphinx pyparsing==2.4.7 # via packaging pytest-cov==2.12.1 @@ -158,12 +126,9 @@ python-dateutil==2.8.1 # via # -r requirements/prod.txt # faker -pytz==2021.1 - # via babel pyyaml==5.4.1 # via # -r requirements/prod.txt - # myst-parser # pre-commit # vcrpy regex==2021.4.4 @@ -172,7 +137,6 @@ requests==2.25.1 # via # coveralls # responses - # sphinx responses==0.13.3 # via -r requirements/dev.in six==1.16.0 @@ -183,25 +147,7 @@ six==1.16.0 # tox # vcrpy # virtualenv -snowballstemmer==2.1.0 - # via sphinx -sphinx==3.5.4 - # via - # -r requirements/dev.in - # myst-parser -sphinxcontrib-applehelp==1.0.2 - # via sphinx -sphinxcontrib-devhelp==1.0.2 - # via sphinx -sphinxcontrib-htmlhelp==2.0.0 - # via sphinx -sphinxcontrib-jsmath==1.0.1 - # via sphinx -sphinxcontrib-qthelp==1.0.3 - # via sphinx -sphinxcontrib-serializinghtml==1.1.5 - # via sphinx -sqlalchemy==1.4.17 +sqlalchemy==1.4.18 # via -r requirements/prod.txt text-unidecode==1.3 # via @@ -210,7 +156,6 @@ text-unidecode==1.3 toml==0.10.2 # via # black - # pep517 # pre-commit # pytest # pytest-cov @@ -230,7 +175,6 @@ typing-extensions==3.10.0.0 # -r requirements/prod.txt # black # importlib-metadata - # markdown-it-py # pydantic # yarl urllib3==1.26.5 @@ -253,10 +197,3 @@ zipp==3.4.1 # via # -r requirements/prod.txt # importlib-metadata - # pep517 - -# The following packages are considered to be unsafe in a requirements file: -pip==21.1.2 - # via pip-tools -setuptools==57.0.0 - # via sphinx diff --git a/requirements/prod.txt b/requirements/prod.txt index 5f916a73..a23d94da 100644 --- a/requirements/prod.txt +++ b/requirements/prod.txt @@ -8,7 +8,7 @@ click==7.1.2 # via -r requirements/prod.in contextvars==2.4 # via -r requirements/prod.in -faker==8.6.0 +faker==8.8.1 # via -r requirements/prod.in greenlet==1.1.0 # via sqlalchemy @@ -32,7 +32,7 @@ pyyaml==5.4.1 # via -r requirements/prod.in six==1.16.0 # via python-dateutil -sqlalchemy==1.4.17 +sqlalchemy==1.4.18 # via -r requirements/prod.in text-unidecode==1.3 # via faker From 969fe7602977144f211663815c9573b1659d89a6 Mon Sep 17 00:00:00 2001 From: Paul Prescod Date: Tue, 22 Jun 2021 12:22:09 -0700 Subject: [PATCH 38/53] Update docs/index.md Co-authored-by: James Estevez --- docs/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/index.md b/docs/index.md index a26de230..170cb8b1 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1129,7 +1129,7 @@ because Snowfakery has randomization features, so that a recipe might generate a random number of accounts in each run. Even for simpler recipes, doing the math may be a headache, especially if you are changing the recipe every day. -A better solution is to specify the"target count" and a "target tablename", like this: +A better solution is to specify the "target count" and a "target tablename", like this: ```s snowfakery accounts.yml --target-number 1000 Account From 5c2a9abf057982d387d2a989d6ba7c9d0d939d9c Mon Sep 17 00:00:00 2001 From: Paul Prescod Date: Tue, 22 Jun 2021 12:32:16 -0700 Subject: [PATCH 39/53] Add pip-tools to make dev install --- .github/workflows/ci.yml | 6 +++--- Makefile | 1 + README.md | 1 - 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index cb74703e..c366e76d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -22,7 +22,7 @@ jobs: - name: "Install dependencies" run: | python -VV - python -m pip install --upgrade pip pip-tools + python -m pip install --upgrade pip make dev-install - name: "Run tox targets for ${{ matrix.python-version }}" @@ -49,7 +49,7 @@ jobs: - name: Install dependencies run: | python -VV - python -m pip install --upgrade pip pip-tools + python -m pip install --upgrade pip make dev-install python -m pip install cumulusci @@ -71,7 +71,7 @@ jobs: - name: "Install dependencies" run: | python -VV - python -m pip install --upgrade pip pip-tools + python -m pip install --upgrade pip make dev-install - name: Run Tests diff --git a/Makefile b/Makefile index ddeb5f3e..ed4bf420 100644 --- a/Makefile +++ b/Makefile @@ -3,4 +3,5 @@ update-deps: pip-compile --upgrade --allow-unsafe requirements/dev.in dev-install: + pip install --upgrade pip-tools pip-sync requirements/*.txt diff --git a/README.md b/README.md index ee33b7b9..ad611803 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,6 @@ Once you have youre virtual environment, you can install dependencies via pip: Or you can install dependencies via pip tools: ```python -pip install pip-tools make dev-install ``` From eed67666b9b59f84c44aa067675271b664635568 Mon Sep 17 00:00:00 2001 From: Paul Prescod Date: Tue, 22 Jun 2021 12:39:22 -0700 Subject: [PATCH 40/53] Responses to pull request --- docs/index.md | 2 +- tests/test_cli.py | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/docs/index.md b/docs/index.md index 170cb8b1..dcfb9a4d 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1129,7 +1129,7 @@ because Snowfakery has randomization features, so that a recipe might generate a random number of accounts in each run. Even for simpler recipes, doing the math may be a headache, especially if you are changing the recipe every day. -A better solution is to specify the "target count" and a "target tablename", like this: +A better solution is to specify the "target number" and a "target tablename", like this: ```s snowfakery accounts.yml --target-number 1000 Account diff --git a/tests/test_cli.py b/tests/test_cli.py index 43bd9b53..3232c4c2 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -421,6 +421,14 @@ def test_mutually_exclusive(self): ) assert "apping-file" in str(e.value) + def test_mutually_exclusive_targets(self): + with pytest.raises(ClickException) as e: + generate_cli.main( + [str(sample_yaml), "--reps", "50", "--target-count", "Account", "100"], + standalone_mode=False, + ) + assert "mutually exclusive" in str(e.value) + def test_cli_errors__cannot_infer_output_format(self): with pytest.raises(ClickException, match="No format supplied"): with TemporaryDirectory() as t: From a1301a82b33441f38f5beb10497708b2cd7a77ea Mon Sep 17 00:00:00 2001 From: Paul Prescod Date: Tue, 22 Jun 2021 14:42:02 -0700 Subject: [PATCH 41/53] Update HISTORY.md --- HISTORY.md | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/HISTORY.md b/HISTORY.md index f50a949c..775cec8e 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -6,7 +6,8 @@ And so [Salesforce.org](http://salesforce.org/) said “Let there be data,” an ## Snowfakery 2.0 -Recipes can now merge in data from Salesforce. (#395) +Recipes can now merge in data from Salesforce Salesforce instances as +records, IDs or datasets. (#395 and #401) Output streams can now be specified as 3rd party libraries. Any Python classname can be passed to --output-format as long as it adheres to the OutputStream @@ -15,7 +16,20 @@ protocol as shown in examples/YamlOutputStream.py (#351) Snowfakery is thread-safe/multi-processor-ready and available for parallel usage in CumulusCI. (CumulusCI Repo) -Snowfakery now supports a more intuitive and properly documented fake list. (TBD) +Snowfakery now supports a --reps option as an easier way to repeat a recipe (#416) + +Snowfakery now accepts LeadingCaps syntax for all fakers, as well as +underscore_separated and everythinglowercase. (#403) + +Snowfakery now supports a more intuitive and properly documented fake list. (#409 Not merged yet) + +Salesforce.ContentVersion and Salesforce.ProfileId convenience functions were added +(#421 Not merged yet) + +Email and Username are based on FirstName and LastName if available (#420 Not merged yet) + +Snowfakery now has voluminous documentation about Fakes in many languages and +locales (#409) ## Snowfakery 1.12 From 5237a9a371bbaed6acc1e987bba97836501eb324 Mon Sep 17 00:00:00 2001 From: Paul Prescod Date: Tue, 22 Jun 2021 15:21:14 -0700 Subject: [PATCH 42/53] Release a dev-release of Snowfakery to allow CCI tests to pass. --- snowfakery/version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/snowfakery/version.txt b/snowfakery/version.txt index 35d51f33..c45502d3 100644 --- a/snowfakery/version.txt +++ b/snowfakery/version.txt @@ -1 +1 @@ -1.12 \ No newline at end of file +2.0.dev0 \ No newline at end of file From e57f458cf0a2754e8ada732a48ea8ff57a87eecb Mon Sep 17 00:00:00 2001 From: Paul Prescod Date: Sat, 26 Jun 2021 08:51:26 -0700 Subject: [PATCH 43/53] Clean up SQL Alchemy warning --- snowfakery/output_streams.py | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/snowfakery/output_streams.py b/snowfakery/output_streams.py index 096a94ca..c95f9a99 100644 --- a/snowfakery/output_streams.py +++ b/snowfakery/output_streams.py @@ -10,7 +10,16 @@ from typing import Dict, Union, Optional, Mapping, Callable, Sequence from warnings import warn -from sqlalchemy import create_engine, MetaData, Column, Integer, Table, Unicode, func +from sqlalchemy import ( + create_engine, + MetaData, + Column, + Integer, + Table, + Unicode, + func, + inspect, +) from sqlalchemy.ext.automap import automap_base from sqlalchemy.orm import create_session from sqlalchemy.engine import Engine @@ -396,6 +405,7 @@ def close(self, *args, **kwargs): def create_tables_from_inferred_fields(tables, engine, metadata): """Create tables based on dictionary of tables->field-list.""" with engine.connect() as conn: + inspector = inspect(engine) for table_name, table in tables.items(): columns = [Column(field_name, Unicode(255)) for field_name in table.fields] id_column_as_list = [ @@ -412,7 +422,8 @@ def create_tables_from_inferred_fields(tables, engine, metadata): ) t = Table(table_name, metadata, id_column, *columns) - if t.exists(): + + if inspector.has_table(table_name): stmt = select([func.count(t.c.id)]) count = conn.execute(stmt).first()[0] if count > 0: From 1340a4681bb465015db5efcc03c1344940963b77 Mon Sep 17 00:00:00 2001 From: Paul Prescod Date: Sat, 26 Jun 2021 15:23:09 -0700 Subject: [PATCH 44/53] Allow building specific locales for testing --- tools/faker_docs_utils/faker_markdown.py | 17 +++++++++++------ .../mkdocs_plugins/main_mkdocs_plugin.py | 17 ++++++++++------- 2 files changed, 21 insertions(+), 13 deletions(-) diff --git a/tools/faker_docs_utils/faker_markdown.py b/tools/faker_docs_utils/faker_markdown.py index dfae0174..43a9284a 100644 --- a/tools/faker_docs_utils/faker_markdown.py +++ b/tools/faker_docs_utils/faker_markdown.py @@ -1,6 +1,7 @@ import re from functools import lru_cache from pathlib import Path +import typing as T from yaml import dump as yaml_dump from faker import Faker @@ -42,7 +43,7 @@ def country_for_locale(locale: str): return f.current_country() -def locales_as_markdown(current_locale: str): +def locales_as_markdown(current_locale: str, locale_list: T.List[str]): def format_link(locale: str): try: country_name = country_for_locale(locale) @@ -52,7 +53,7 @@ def format_link(locale: str): link_text = f"{language} as spoken in {country_name}: ({locale})" return f" - [{link_text}](fakedata/{locale}.md)\n" - other_locales = [locale for locale in AVAILABLE_LOCALES if locale != current_locale] + other_locales = [locale for locale in locale_list if locale != current_locale] links = [format_link(locale) for locale in other_locales] return " ".join(link for link in links if link) @@ -129,7 +130,7 @@ def output_faker(name: str, data: str, output: callable, locale: str): output("Aliases: ", ", ".join(data.aliases)) output() - link = f"[{data.source}]({data.url})" + link = f"[{data.source}]({data.url}) : {data.fullname}" output("Source:", link) if samples: @@ -155,20 +156,24 @@ def prefix(line): return "\n".join(lines) -def generate_markdown_for_all_locales(path: Path, locales=AVAILABLE_LOCALES): +def generate_markdown_for_all_locales(path: Path, locales=None): + "Generate markdown file for each listed locale. None means all locales" + locales = locales or AVAILABLE_LOCALES for locale in locales: with Path(path, f"{locale}.md").open("w") as f: print(f.name) generate_markdown_for_fakers(f, locale) -def generate_locales_index(path: Path): +def generate_locales_index(path: Path, locales_list: T.List[str]): + "Generate markdown index including listed locales. None means all locales" + locales_list = locales_list or AVAILABLE_LOCALES with Path(path).open("w") as outfile: def output(*args, **kwargs): print(*args, **kwargs, file=outfile) - locales = locales_as_markdown(None) + locales = locales_as_markdown(None, locales_list) if locales: output("## Fake Data Locales\n") output( diff --git a/tools/faker_docs_utils/mkdocs_plugins/main_mkdocs_plugin.py b/tools/faker_docs_utils/mkdocs_plugins/main_mkdocs_plugin.py index 77710b8a..e4834cd8 100644 --- a/tools/faker_docs_utils/mkdocs_plugins/main_mkdocs_plugin.py +++ b/tools/faker_docs_utils/mkdocs_plugins/main_mkdocs_plugin.py @@ -55,12 +55,15 @@ def new_warning(self, *args, **kwargs): with fakerdocs_md.open("w") as f: generate_markdown_for_fakers(f, "en_US", main_header) - build_locales_env = os.environ.get("SF_MKDOCS_BUILD_LOCALES") - if build_locales_env: - build_locales = build_locales_env != "False" + build_locales_env = os.environ.get( + "SF_MKDOCS_BUILD_LOCALES" + ) or self.config.get("build_locales") + if build_locales_env == "False": + locales_list = ["en_US", "fr_FR"] + elif build_locales_env: + locales_list = build_locales_env.split(",") else: - build_locales = self.config.get("build_locales") + locales_list = None # means "all" - if build_locales: - generate_markdown_for_all_locales(faker_docs_dir) - generate_locales_index("docs/locales.md") + generate_markdown_for_all_locales(faker_docs_dir, locales_list) + generate_locales_index("docs/locales.md", locales_list) From 703fa3f93f4056851e0460b01499cfed606b615d Mon Sep 17 00:00:00 2001 From: Paul Prescod Date: Wed, 30 Jun 2021 07:23:36 -0700 Subject: [PATCH 45/53] Test case for multiple friends --- tests/test_friends.py | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 tests/test_friends.py diff --git a/tests/test_friends.py b/tests/test_friends.py new file mode 100644 index 00000000..1aa6eed6 --- /dev/null +++ b/tests/test_friends.py @@ -0,0 +1,23 @@ +from io import StringIO + +from snowfakery.data_generator import generate + + +class TestFriends: + def test_multiple_friends(self, generated_rows): + yaml = """ + - object: Account + - object: Account + friends: + - object: Contact + fields: + AccountId: + reference: Account + - object: Contact + fields: + AccountId: + reference: Account + """ + generate(StringIO(yaml), {}) + assert generated_rows.table_values("Contact", 0, "AccountId") == "Account(2)" + assert generated_rows.table_values("Contact", 1, "AccountId") == "Account(2)" From 4d08154327323d4c3d4daf4dbe6905301b5fc891 Mon Sep 17 00:00:00 2001 From: Paul Prescod Date: Wed, 30 Jun 2021 13:11:22 -0700 Subject: [PATCH 46/53] Docstrings and warnings cleanups --- mkdocs.yml | 3 +- tools/faker_docs_utils/faker_markdown.py | 39 ++++--- tools/faker_docs_utils/format_samples.py | 103 ++++++++++-------- .../mkdocs_plugins/main_mkdocs_plugin.py | 10 +- tools/faker_docs_utils/summarize_fakers.py | 33 +++--- 5 files changed, 107 insertions(+), 81 deletions(-) diff --git a/mkdocs.yml b/mkdocs.yml index 09ab2232..b6a1461d 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -1,7 +1,8 @@ site_name: Snowfakery documentation site_url: "" +use_directory_urls: False theme: readthedocs -theme_dir: custom_theme +custom_dir: custom_theme repo_url: https://github.com/SFDO-Tooling/Snowfakery/ nav: - index.md diff --git a/tools/faker_docs_utils/faker_markdown.py b/tools/faker_docs_utils/faker_markdown.py index 43a9284a..87dd2c8e 100644 --- a/tools/faker_docs_utils/faker_markdown.py +++ b/tools/faker_docs_utils/faker_markdown.py @@ -10,7 +10,7 @@ yaml_samples_for_docstring, snowfakery_output_for, ) -from .summarize_fakers import get_all_fakers +from .summarize_fakers import summarize_all_fakers from .language_codes import language_codes from snowfakery.fakedata.fake_data_generator import FakeData @@ -27,7 +27,8 @@ ] -def strip(my_str): +def cleanup_docstring(my_str): + "Clean up a docstring to remove Faker-doc weirdness and excesss whitespace" my_str = _RE_COMBINE_WHITESPACE.sub("", my_str) my_str = _RE_STRIP_SAMPLES.sub("", my_str).strip() my_str = _COMMENT_LINES_THAT_LOOK_LIKE_TITLES.sub(" #", my_str) @@ -43,7 +44,9 @@ def country_for_locale(locale: str): return f.current_country() -def locales_as_markdown(current_locale: str, locale_list: T.List[str]): +def locales_as_markdown_links(current_locale: str, locale_list: T.List[str]): + "Generate a list of Markdown locale links" + def format_link(locale: str): try: country_name = country_for_locale(locale) @@ -62,11 +65,12 @@ def format_link(locale: str): def generate_markdown_for_fakers(outfile, locale: str, header: str = standard_header): + "Generate the Markdown page for a locale" faker = Faker(locale) language = language_codes[locale.split("_")[0]] fd = FakeData(faker) - all_fakers = get_all_fakers(fd) + all_fakers = summarize_all_fakers(fd) def output(*args, **kwargs): print(*args, **kwargs, file=outfile) @@ -81,12 +85,15 @@ def output(*args, **kwargs): output("[TOC]\n") output("## Commonly Used\n") - summarize_categories(output, [f for f in all_fakers if f.common], "", locale) + output_fakers_in_categories(output, [f for f in all_fakers if f.common], "", locale) output("## Rarely Used\n") - summarize_categories(output, [f for f in all_fakers if not f.common], "", locale) + output_fakers_in_categories( + output, [f for f in all_fakers if not f.common], "", locale + ) -def summarize_categories(output, fakers, common: str, locale): +def output_fakers_in_categories(output, fakers, common: str, locale): + """Sort fakers into named categores and then output them""" categorized = categorize(fakers) for category_name, fakers in categorized.items(): output(f"### {category_name.title()} Fakers\n") @@ -95,6 +102,7 @@ def summarize_categories(output, fakers, common: str, locale): def categorize(fakers): + "Sort fakers based on their categories (what module they came from)" categories = {} for fakerdata in fakers: category = fakerdata.category @@ -104,28 +112,30 @@ def categorize(fakers): def gather_samples(name, data, locale): - if data.sample: + if data.sample: # I already have a sample, no need to generate one if locale and locale != "en_US": locale_header = [{"var": "snowfakery_locale", "value": locale}] sample = locale_header + data.sample else: sample = data.sample example = yaml_dump(sample, sort_keys=False) - samples = [snowfakery_output_for(data.name, example)] - else: + samples = [snowfakery_output_for(data.name, example, example)] + else: # need to generate a sample from scratch samples = yaml_samples_for_docstring(name, data.fullname, data.doc, locale) return list(filter(None, samples)) def output_faker(name: str, data: str, output: callable, locale: str): + """Output the data relating to a particular faker""" samples = gather_samples(name, data, locale) # if there isn't at least one sample, don't publish if not samples: return output(f"#### fake: {name}\n") - if strip(data.doc): - output(strip(data.doc)) + cleaned_docstring = cleanup_docstring(data.doc) + if cleaned_docstring: + output(cleaned_docstring) output() output("Aliases: ", ", ".join(data.aliases)) @@ -146,7 +156,8 @@ def output_faker(name: str, data: str, output: callable, locale: str): output() -def indent(yaml): +def indent(yaml: str): + """Add indents to yaml""" lines = yaml.split("\n") def prefix(line): @@ -173,7 +184,7 @@ def generate_locales_index(path: Path, locales_list: T.List[str]): def output(*args, **kwargs): print(*args, **kwargs, file=outfile) - locales = locales_as_markdown(None, locales_list) + locales = locales_as_markdown_links(None, locales_list) if locales: output("## Fake Data Locales\n") output( diff --git a/tools/faker_docs_utils/format_samples.py b/tools/faker_docs_utils/format_samples.py index 0df7799d..2ddb4b68 100644 --- a/tools/faker_docs_utils/format_samples.py +++ b/tools/faker_docs_utils/format_samples.py @@ -9,10 +9,12 @@ from . import docstring -ALREADY_GENERATED_ERROR_FOR = set() +# known code gen issues. ignore them. +IGNORE_ERRORS = set(("uuid4", "randomchoices", "randomelement", "randomelements")) def samples_from_docstring(fullname, docstring_data): + """Convert a Faker-style docstring into a Snowfaery sample""" lines = docstring_data.split("\n") lines = [line.strip() for line in lines] docstrings = docstring.ProviderMethodDocstring( @@ -27,19 +29,27 @@ def samples_from_docstring(fullname, docstring_data): def simplify(arg): + """Simplify Faker arg-types. e.g. tuples become lists. OrdereDicts become dicts""" fieldname = arg._fields[0] out = getattr(arg, fieldname) + + # primitives are fine if isinstance(out, (str, int, float, bool)): return out + + # simplify tuples to lists, and simplify the contents if isinstance(out, (list, tuple)): args = [simplify(a) for a in out] return type(out)(args) + + # simplify OrderedDicts to dicts, and simplify the contents if isinstance(out, (OrderedDict, dict)): return {name: simplify(value) for name, value in dict(out).items()} raise TypeError(type(out), out) def extract_keywords(kwargstr): + """Reverse engineer the params from a Snowfakery faker by using the Python parser""" fake_python = f"Func({kwargstr})" tree = ast.parse(fake_python, mode="eval") kwds = {arg.arg: simplify(arg.value) for arg in tree.body.keywords} @@ -47,25 +57,28 @@ def extract_keywords(kwargstr): def reformat_yaml(yaml_data): + """Normalize YAML to a common format""" data = yaml.safe_load(yaml_data) return yaml.dump(data, sort_keys=False) def yaml_samples_for_docstring_sample(name, sample, locale): + """Try to generate Snowfakery input and output for a faker.""" try: - return yaml_samples_for_docstring_sample_inner(name, sample, locale) + return _yaml_samples_for_docstring_sample_inner(name, sample, locale) except Exception as e: - print("Cannot generate sample for", sample, str(e)[0:100]) + print("Cannot generate sample from docstring", sample, str(e)[0:100]) raise e -def yaml_samples_for_docstring_sample_inner(name, sample, locale): +def _yaml_samples_for_docstring_sample_inner(name, sample, locale): + """Try to generate Snowfakery input and output for a faker.""" try: kwds = extract_keywords(sample.kwargs) except Exception as e: - if name not in ALREADY_GENERATED_ERROR_FOR: - ALREADY_GENERATED_ERROR_FOR.add(name) - print("Cannot extract keywords", sample, str(e)[0:100]) + if name.lower() not in IGNORE_ERRORS: + IGNORE_ERRORS.add(name.lower()) + print("Cannot extract keywords", name, sample, str(e)[0:100]) return None name = name.split(".")[-1] @@ -73,6 +86,7 @@ def yaml_samples_for_docstring_sample_inner(name, sample, locale): def yaml_sample(name, kwds, kw_example, locale): + """Generate Snowfakery yaml input and output""" if kwds: inline_example = f"fake.{name}({kw_example})" block_example = {f"fake.{name}": kwds} @@ -85,41 +99,56 @@ def yaml_sample(name, kwds, kw_example, locale): if ":" in inline_example: inline_example = f'"{inline_example}"' - yaml_data = f""" + single_part_example = f""" - object: SomeObject fields: - formula_field_example: {inline_example} - block_field_example: {block_example}""" + formula_field_example: {inline_example}""" if locale: locale_decl = f""" - var: snowfakery_locale value: {locale} """ - yaml_data = locale_decl + yaml_data + single_part_example = locale_decl + single_part_example try: - yaml_data = reformat_yaml(yaml_data) + two_part_example = ( + single_part_example + + f""" + block_field_example: {block_example}""" + ) + + two_part_example = reformat_yaml(two_part_example) + single_part_example = reformat_yaml(single_part_example) except Exception as e: print("CANNOT PARSE") - print(yaml_data) + print(two_part_example, single_part_example) print(str(e)[0:100]) raise - return snowfakery_output_for(name, yaml_data) + return snowfakery_output_for(name, two_part_example, single_part_example) + +def snowfakery_output_for(name, primary_example, secondary_example): + """Generate the Snowfakery output for some YAML -def snowfakery_output_for(name, yaml_data): - with StringIO() as s: - try: - generate_data(StringIO(yaml_data), output_file=s, output_format="txt") - except Exception as e: - if name not in ALREADY_GENERATED_ERROR_FOR: - print(f"Cannot generate sample for {name}: {str(e)[0:50]}") - ALREADY_GENERATED_ERROR_FOR.add(name) + Attempt to generate a two-part example, but fall back to single + or nothing if worse comes to worst.""" + output = None + exception = None + + for yaml_data in [primary_example, secondary_example]: + with StringIO() as s: + try: + generate_data(StringIO(yaml_data), output_file=s, output_format="txt") + output = s.getvalue() + exception = None + except Exception as e: + exception = e + + if exception and name.lower() not in IGNORE_ERRORS: + print(f"Cannot generate sample for {name}: {str(exception)[0:80]}") + IGNORE_ERRORS.add(name.lower()) - # print(yaml_data) - # print(str(e)[0:100]) - output = s.getvalue() if output: return yaml_data, output @@ -129,6 +158,7 @@ def default_yaml_sample(name, locale): def yaml_samples_for_docstring(name, fullname, docstring_data, locale=None): + """Generate example for all samples associated wth a docstring""" sample_objs = samples_from_docstring(fullname, docstring_data) output = [ @@ -138,26 +168,3 @@ def yaml_samples_for_docstring(name, fullname, docstring_data, locale=None): if not output: output = [default_yaml_sample(name, locale)] return output - - -if __name__ == "__main__": - - out = samples_from_docstring( - "faker.providers.BaseProvider.upc_e", - """ together to produce the UPC-E barcode, and attempting to convert the - barcode to UPC-A and back again to UPC-E will exhibit the behavior - described above. - - :sample: - :sample: base='123456' - :sample: base='123456', number_system_digit=0 - :sample: base='123456', number_system_digit=1 - :sample: base='120000', number_system_digit=0 - :sample: base='120003', number_system_digit=0 - :sample: base='120004', number_system_digit=0 - :sample: base='120000', number_system_digit=0, safe_mode=False - :sample: base='120003', number_system_digit=0, safe_mode=False - :sample: base='120004', number_system_digit=0, safe_mode=False""", - ) - - print(out) diff --git a/tools/faker_docs_utils/mkdocs_plugins/main_mkdocs_plugin.py b/tools/faker_docs_utils/mkdocs_plugins/main_mkdocs_plugin.py index e4834cd8..aba8fd48 100644 --- a/tools/faker_docs_utils/mkdocs_plugins/main_mkdocs_plugin.py +++ b/tools/faker_docs_utils/mkdocs_plugins/main_mkdocs_plugin.py @@ -18,7 +18,7 @@ def on_pre_build(self, config): faker_docs_dir = root_dir / "docs/fakedata" faker_docs_dir.mkdir(exist_ok=True) new_sys_path = [*sys.path, str(root_dir)] - print("Note: Hiding warnings during build", __file__) + print("Note: Hiding warnings during docs build") # make modules available sys_path_patch = patch.object(sys, "path", new_sys_path) @@ -57,13 +57,15 @@ def new_warning(self, *args, **kwargs): build_locales_env = os.environ.get( "SF_MKDOCS_BUILD_LOCALES" - ) or self.config.get("build_locales") + ) or self.config.get("build_locales", None) if build_locales_env == "False": locales_list = ["en_US", "fr_FR"] - elif build_locales_env: + elif build_locales_env in (True, "True", None): + locales_list = None # means "all" + elif isinstance(build_locales_env, str): locales_list = build_locales_env.split(",") else: - locales_list = None # means "all" + assert 0, f"Unexpected build_locales_env {build_locales_env}" generate_markdown_for_all_locales(faker_docs_dir, locales_list) generate_locales_index("docs/locales.md", locales_list) diff --git a/tools/faker_docs_utils/summarize_fakers.py b/tools/faker_docs_utils/summarize_fakers.py index 0f906ab7..cb005c29 100644 --- a/tools/faker_docs_utils/summarize_fakers.py +++ b/tools/faker_docs_utils/summarize_fakers.py @@ -5,9 +5,23 @@ import yaml -def get_all_fakers(faker): +class FakerInfo(T.NamedTuple): + name: str + fullname: str + aliases: T.List[str] + url: str + source: str + category: str + doc: str + common: bool + sample: str + + +def summarize_all_fakers(faker) -> T.Sequence[FakerInfo]: + """Summarize information about all fakers""" from snowfakery.utils.collections import CaseInsensitiveDict + # get config info that can override samples etc. with (Path(__file__).parent / "docs_config.yml").open() as f: yaml_data = yaml.safe_load(f) common_fakes = yaml_data["common_fakes"] @@ -17,6 +31,7 @@ def get_all_fakers(faker): for name, meth in faker.fake_names.items(): if not isinstance(meth, types.MethodType): continue + # python magic to introspect classnames, filenames, etc. friendly = _to_camel_case(name) func = meth.__func__ doc = func.__doc__ @@ -25,6 +40,8 @@ def get_all_fakers(faker): fullname = cls.__module__ + "." + cls.__name__ + "." + meth.__name__ overrides = common_fakes.get(meth.__name__) or uncommon_fakes.get(meth.__name__) is_common = meth.__name__ in common_fakes + + # if it came from Faker if "/faker/" in filename: source = "faker" idx = filename.find("/faker/") @@ -33,7 +50,7 @@ def get_all_fakers(faker): while parts[-1] in ("__init__.py", "en_US"): del parts[-1] category = parts[-1] - else: + else: # if it came from Snowfakery source = "snowfakery" idx = filename.find("/snowfakery/") url = ( @@ -60,18 +77,6 @@ def get_all_fakers(faker): return faker_infos.values() -class FakerInfo(T.NamedTuple): - name: str - fullname: str - aliases: T.List[str] - url: str - source: str - category: str - doc: str - common: bool - sample: str - - def _to_camel_case(snake_str): components = snake_str.split("_") return "".join(x.title() for x in components) From 4b4e71a16028d797f8772880819155ecc71013e6 Mon Sep 17 00:00:00 2001 From: Paul Prescod Date: Wed, 30 Jun 2021 20:20:26 -0700 Subject: [PATCH 47/53] Snowfakery accepts an org_config and project_config for Salesforce queries --- docs/salesforce.md | 6 +- snowfakery/data_generator.py | 2 +- snowfakery/standard_plugins/Salesforce.py | 107 +++++++++++++++------- tests/salesforce/test_where.recipe.yml | 2 +- tests/test_with_cci.py | 79 +++++++++------- 5 files changed, 123 insertions(+), 73 deletions(-) diff --git a/docs/salesforce.md b/docs/salesforce.md index bcb408ff..b56d1ee2 100644 --- a/docs/salesforce.md +++ b/docs/salesforce.md @@ -217,11 +217,11 @@ In general, you can test Snowfakery files outside of CumulusCI to see if they wo $ snowfakery recipe.yml ``` -If you have a recipe which depends on data from an org, specify the CumulusCI orgname -like this: +If you have a recipe which depends on data from an org, +specify the CumulusCI org name like this: ```s -$ snowfakery recipe.yml --plugin-options orgname qa +$ snowfakery recipe.yml --plugin-options org_name qa ``` When you run the recipe in this way, it will connect to the org to pull data but diff --git a/snowfakery/data_generator.py b/snowfakery/data_generator.py index 983cac58..eab8ccaf 100644 --- a/snowfakery/data_generator.py +++ b/snowfakery/data_generator.py @@ -192,7 +192,7 @@ def process_plugins_options( ) -> Mapping[str, object]: """Replace option short names with fully qualified names and convert types of options. - e.g. the option name that the user specifies on the CLI or API is just "orgname" + e.g. the option name that the user specifies on the CLI or API is just "org_name" but we use the long name internally to avoid clashing with the user's variable names.""" diff --git a/snowfakery/standard_plugins/Salesforce.py b/snowfakery/standard_plugins/Salesforce.py index bfc17944..9eb0a5a9 100644 --- a/snowfakery/standard_plugins/Salesforce.py +++ b/snowfakery/standard_plugins/Salesforce.py @@ -29,10 +29,18 @@ MAX_SALESFORCE_OFFSET = 2000 # Any way around this? -# the option name that the user specifies on the CLI or API is just "orgname" +# the option name that the user specifies on the CLI or API is just "org_name" # but using this long name internally prevents us from clashing with the # user's variable names. -plugin_option_name = "snowfakery.standard_plugins.Salesforce.SalesforceQuery.orgname" +plugin_option_org_name = ( + "snowfakery.standard_plugins.Salesforce.SalesforceQuery.org_name" +) +plugin_option_org_config = ( + "snowfakery.standard_plugins.Salesforce.SalesforceQuery.org_config" +) +plugin_option_project_config = ( + "snowfakery.standard_plugins.Salesforce.SalesforceQuery.project_config" +) class SalesforceConnection: @@ -40,15 +48,16 @@ class SalesforceConnection: _sf = None - def __init__(self, get_orgname): - self.get_orgname = get_orgname + def __init__(self, get_project_config_and_org_config): + self.get_project_config_and_org_config = get_project_config_and_org_config self.logger = getLogger(__name__) @property def sf(self): """simple_salesforce client""" if not self._sf: - self._sf, self._bulk = self._get_sf_clients(self.orgname) + project_config, org_config = self.get_project_config_and_org_config() + self._sf, self._bulk = self._get_sf_clients(project_config, org_config) return self._sf @property @@ -57,11 +66,6 @@ def bulk(self): self.sf # initializes self._bulk as a side-effect return self._bulk - @property - def orgname(self): - """Look up the orgname in the scope""" - return self.get_orgname() - def query(self, *args, **kwargs): """Query Salesforce through simple_salesforce""" return self.sf.query(*args, **kwargs) @@ -108,50 +112,85 @@ def compose_query(self, context_name, **kwargs): return query @staticmethod - def _get_sf_clients(orgname): + def _get_sf_clients(project_config, org_config): + from cumulusci.salesforce_api.utils import get_simple_salesforce_connection - try: - from cumulusci.cli.runtime import CliRuntime - from cumulusci.salesforce_api.utils import get_simple_salesforce_connection + sf = get_simple_salesforce_connection(project_config, org_config) + return sf, _init_bulk(sf, org_config) - runtime = CliRuntime(load_keychain=True) - except Exception as e: # pragma: no cover - raise DataGenError("CumulusCI Runtime cannot be loaded", *e.args) - name, org_config = runtime.get_org(orgname) - sf = get_simple_salesforce_connection(runtime.project_config, org_config) - return sf, SalesforceConnection._init_bulk(sf, org_config) +def _init_bulk(sf, org_config): + from salesforce_bulk import SalesforceBulk - @staticmethod - def _init_bulk(sf, org_config): - from salesforce_bulk import SalesforceBulk + return SalesforceBulk( + host=org_config.instance_url.replace("https://", "").rstrip("/"), + sessionId=org_config.access_token, + API_version=sf.sf_version, + ) - return SalesforceBulk( - host=org_config.instance_url.replace("https://", "").rstrip("/"), - sessionId=org_config.access_token, - API_version=sf.sf_version, - ) + +def check_orgconfig(config): + from cumulusci.core.config import BaseConfig + + if isinstance(config, BaseConfig): + return config + raise TypeError(f"Should be a CCI Config, not {type(config)}") class SalesforceConnectionMixin: _sf_connection = None - allowed_options = [PluginOption(plugin_option_name, str)] + _runtime = None + allowed_options = [ + PluginOption(plugin_option_org_name, str), + PluginOption(plugin_option_org_config, check_orgconfig), + PluginOption(plugin_option_project_config, check_orgconfig), + ] @property def sf_connection(self): assert self.context if not self._sf_connection: - self._sf_connection = SalesforceConnection(self.get_orgname) + self._sf_connection = SalesforceConnection( + self.get_project_config_and_org_config + ) return self._sf_connection - def get_orgname(self): - """Look up the orgname in the scope""" + def get_project_config_and_org_config(self): + fieldvars = self.context.field_vars() + project_config = fieldvars.get(plugin_option_project_config) + org_config = fieldvars.get(plugin_option_org_config) + + if not project_config or not org_config: + project_config, org_config = self._get_org_info_from_cli_keychain() + + return project_config, org_config + + def _get_org_info_from_cli_keychain(self): + org_name = self.get_org_name() # from command line argument + runtime = self._get_CliRuntime() # from CCI CliRuntime + name, org_config = runtime.get_org(org_name) + return runtime.project_config, org_config + + def _get_CliRuntime(self): + if self._runtime: + return self._runtime # pragma: no cover + + try: + from cumulusci.cli.runtime import CliRuntime + + self._runtime = CliRuntime(load_keychain=True) + return self._runtime + except Exception as e: # pragma: no cover + raise DataGenError("CumulusCI Runtime cannot be loaded", *e.args) + + def get_org_name(self): + """Look up the org_name in the scope""" fieldvars = self.context.field_vars() try: - return fieldvars[plugin_option_name] + return fieldvars[plugin_option_org_name] except KeyError: raise DataGenNameError( - "Orgname is not specified. Use --plugin-option orgname ", + "Orgname is not specified. Use --plugin-option org_name ", None, None, ) diff --git a/tests/salesforce/test_where.recipe.yml b/tests/salesforce/test_where.recipe.yml index 20bcf05d..88983b6c 100644 --- a/tests/salesforce/test_where.recipe.yml +++ b/tests/salesforce/test_where.recipe.yml @@ -1,6 +1,6 @@ # execute this recipe like this: -# snowfakery tests/salesforce/test_where.recipe.yml --plugin-option orgname qa +# snowfakery tests/salesforce/test_where.recipe.yml --plugin-option org_name qa - plugin: snowfakery.standard_plugins.Salesforce.SalesforceQuery diff --git a/tests/test_with_cci.py b/tests/test_with_cci.py index 09eb39f7..49b549d5 100644 --- a/tests/test_with_cci.py +++ b/tests/test_with_cci.py @@ -13,6 +13,7 @@ from snowfakery.data_generator import generate from snowfakery.data_gen_exceptions import DataGenError from snowfakery import generate_data +from snowfakery.standard_plugins import Salesforce try: import cumulusci @@ -29,11 +30,6 @@ sample_yaml = Path(__file__).parent / "include_parent.yml" -skip_if_cumulusci_missing = pytest.mark.skipif( - not hasattr(cumulusci, "api"), reason="CumulusCI not installed" -) - - class Test_CLI_CCI: # @skip_if_cumulusci_missing def test_mapping_file(self): @@ -92,7 +88,7 @@ def test_soql_plugin_random(self, fake_sf_client, generated_rows): AccountId: SalesforceQuery.random_record: Account """ - generate(StringIO(yaml), plugin_options={"orgname": "blah"}) + generate(StringIO(yaml), plugin_options={"org_name": "blah"}) assert fake_sf_client.mock_calls assert generated_rows.row_values(0, "AccountId") == "FAKEID5" @@ -113,7 +109,7 @@ def test_soql_plugin_no_query_from(self, fake_sf_client, generated_rows): where: Name='Foo' """ with pytest.raises(DataGenError, match="Must supply 'from:'"): - generate(StringIO(yaml), plugin_options={"orgname": "blah"}) + generate(StringIO(yaml), plugin_options={"org_name": "blah"}) def test_soql_plugin_record(self, fake_sf_client, generated_rows): yaml = """ @@ -125,7 +121,7 @@ def test_soql_plugin_record(self, fake_sf_client, generated_rows): AccountId: SalesforceQuery.find_record: Account """ - generate(StringIO(yaml), plugin_options={"orgname": "blah"}) + generate(StringIO(yaml), plugin_options={"org_name": "blah"}) assert fake_sf_client.mock_calls assert generated_rows.row_values(0, "AccountId") == "FAKEID0" @@ -140,18 +136,39 @@ def test_soql_plugin_random__orgname_long(self, fake_sf_client, generated_rows): SalesforceQuery.random_record: Account """ plugin_option_name = ( - "snowfakery.standard_plugins.Salesforce.SalesforceQuery.orgname" + "snowfakery.standard_plugins.Salesforce.SalesforceQuery.org_name" ) generate(StringIO(yaml), plugin_options={plugin_option_name: "blah"}) assert fake_sf_client.mock_calls assert generated_rows.row_values(0, "AccountId") == "FAKEID5" +class TestCCIError: + def test_pretend_cci_not_available(self): + filename = ( + Path(__file__).parent.parent / "examples/salesforce_soql_example.recipe.yml" + ) + with unittest.mock.patch( + "snowfakery.standard_plugins.Salesforce.SalesforceConnectionMixin._get_CliRuntime" + ) as conn: + conn.side_effect = ImportError("CumulusCI Runtime cannot be loaded") + with pytest.raises(Exception, match="CumulusCI Runtime cannot be loaded"): + generate_data(filename, plugin_options={"org_name": "None"}) + + @pytest.mark.skipif(cumulusci, reason="CCI is installed") + def test_cci_really_not_available(self): + filename = ( + Path(__file__).parent.parent / "examples/salesforce_soql_example.recipe.yml" + ) + with pytest.raises(Exception, match="CumulusCI Runtime cannot be loaded"): + generate_data(filename, plugin_options={"org_name": "None"}) + + @skip_if_cumulusci_missing class TestSOQLWithCCI: @patch("snowfakery.standard_plugins.Salesforce.randrange", lambda *arg, **kwargs: 0) @pytest.mark.vcr() - def test_soql(self, sf, org_config, generated_rows): + def test_soql(self, sf, org_config, project_config, generated_rows): yaml = """ - plugin: snowfakery.standard_plugins.Salesforce.SalesforceQuery - object: Contact @@ -169,7 +186,10 @@ def test_soql(self, sf, org_config, generated_rows): """ assert org_config.name sf.Account.create({"Name": "Company"}) - generate(StringIO(yaml), plugin_options={"orgname": org_config.name}) + generate( + StringIO(yaml), + plugin_options={"org_config": org_config, "project_config": project_config}, + ) assert len(generated_rows.mock_calls) == 2 @pytest.mark.vcr() @@ -216,22 +236,9 @@ def test_example_through_api(self, sf, generated_rows, org_config): filename = ( Path(__file__).parent.parent / "examples/salesforce_soql_example.recipe.yml" ) - generate_data(filename, plugin_options={"orgname": org_config.name}) + generate_data(filename, plugin_options={"org_name": org_config.name}) assert generated_rows.mock_calls - def test_cci_not_available(self): - filename = ( - Path(__file__).parent.parent / "examples/salesforce_soql_example.recipe.yml" - ) - with unittest.mock.patch( - "snowfakery.standard_plugins.Salesforce.SalesforceConnection._get_sf_clients" - ) as conn: - conn.side_effect = ImportError( - "cumulusci module cannot be loaded by snowfakery" - ) - with pytest.raises(Exception, match="cumulusci module cannot be loaded"): - generate_data(filename, plugin_options={"orgname": "None"}) - @pytest.mark.vcr() def test_find_records_returns_nothing(self, org_config): yaml = """ @@ -244,7 +251,7 @@ def test_find_records_returns_nothing(self, org_config): SalesforceQuery.find_record: Contract """ with pytest.raises(DataGenError, match="No records returned"): - generate_data(StringIO(yaml), plugin_options={"orgname": org_config.name}) + generate_data(StringIO(yaml), plugin_options={"org_name": org_config.name}) @pytest.mark.vcr() def test_find_records_returns_multiple(self, org_config, sf, generated_rows): @@ -257,7 +264,7 @@ def test_find_records_returns_multiple(self, org_config, sf, generated_rows): AccountId: SalesforceQuery.find_record: User """ - generate_data(StringIO(yaml), plugin_options={"orgname": org_config.name}) + generate_data(StringIO(yaml), plugin_options={"org_name": org_config.name}) first_user_id = sf.query("select Id from User")["records"][0]["Id"] assert generated_rows.mock_calls[0][1][1]["AccountId"] == first_user_id @@ -272,7 +279,7 @@ def test_soql_dataset_shuffled(self, sf, org_config, generated_rows): Path(__file__).parent.parent / "examples/soql_dataset_shuffled.recipe.yml" ) - generate_data(filename, plugin_options={"orgname": org_config.name}) + generate_data(filename, plugin_options={"org_name": org_config.name}) assert len(generated_rows.mock_calls) == 10 for mock_call in generated_rows.mock_calls: @@ -293,7 +300,7 @@ def test_soql_dataset_shuffled(self, sf, org_config, generated_rows): def test_soql_dataset_in_order(self, sf, org_config, generated_rows): filename = Path(__file__).parent.parent / "examples/soql_dataset.recipe.yml" - generate_data(filename, plugin_options={"orgname": org_config.name}) + generate_data(filename, plugin_options={"org_name": org_config.name}) assert len(generated_rows.mock_calls) == 10 for mock_call in generated_rows.mock_calls: @@ -321,7 +328,7 @@ def test_soql_dataset_where(self, sf, org_config, generated_rows): Path(__file__).parent.parent / "examples/soql_dataset_where.recipe.yml" ) - generate_data(filename, plugin_options={"orgname": org_config.name}) + generate_data(filename, plugin_options={"org_name": org_config.name}) assert len(generated_rows.mock_calls) == 10 for mock_call in generated_rows.mock_calls: @@ -361,7 +368,7 @@ def download_file(*args, **kwargs): download_file, ) with pretend_5000, do_not_really_download: - generate_data(filename, plugin_options={"orgname": org_config.name}) + generate_data(filename, plugin_options={"org_name": org_config.name}) assert len(generated_rows.mock_calls) == 10 @@ -392,7 +399,7 @@ def test_dataset_bad_query(self, org_config, sf, generated_rows): from: Xyzzy """ with pytest.raises(DataGenError, match="Xyzzy"): - generate_data(StringIO(yaml), plugin_options={"orgname": org_config.name}) + generate_data(StringIO(yaml), plugin_options={"org_name": org_config.name}) def test_dataset_no_fields(self, org_config, sf, generated_rows): yaml = """ @@ -405,7 +412,7 @@ def test_dataset_no_fields(self, org_config, sf, generated_rows): junk: Junk2 """ with pytest.raises(DataGenError, match="SOQLDataset needs a 'fields' list"): - generate_data(StringIO(yaml), plugin_options={"orgname": org_config.name}) + generate_data(StringIO(yaml), plugin_options={"org_name": org_config.name}) def test_dataset_no_from(self, org_config, sf, generated_rows): yaml = """ @@ -418,4 +425,8 @@ def test_dataset_no_from(self, org_config, sf, generated_rows): fields: Junk3 """ with pytest.raises(DataGenError, match="SOQLDataset needs a 'from'"): - generate_data(StringIO(yaml), plugin_options={"orgname": org_config.name}) + generate_data(StringIO(yaml), plugin_options={"org_name": org_config.name}) + + def test_config_type_error(self): + with pytest.raises(TypeError): + Salesforce.check_orgconfig(None) From 66ea9b2b863b5adf8a3940b2e3ad6da5c921ec90 Mon Sep 17 00:00:00 2001 From: Paul Prescod Date: Wed, 30 Jun 2021 21:59:48 -0700 Subject: [PATCH 48/53] snowfakery/version.txt --- snowfakery/version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/snowfakery/version.txt b/snowfakery/version.txt index c45502d3..26e0fd45 100644 --- a/snowfakery/version.txt +++ b/snowfakery/version.txt @@ -1 +1 @@ -2.0.dev0 \ No newline at end of file +2.0.dev1 \ No newline at end of file From cdc55478d34333bebff428337f97b796731d7235 Mon Sep 17 00:00:00 2001 From: Paul Prescod Date: Wed, 7 Jul 2021 12:05:00 -0700 Subject: [PATCH 49/53] Snowfakery 2.0 HISTORY --- HISTORY.md | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/HISTORY.md b/HISTORY.md index 775cec8e..06198755 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -21,12 +21,8 @@ Snowfakery now supports a --reps option as an easier way to repeat a recipe (#41 Snowfakery now accepts LeadingCaps syntax for all fakers, as well as underscore_separated and everythinglowercase. (#403) -Snowfakery now supports a more intuitive and properly documented fake list. (#409 Not merged yet) - Salesforce.ContentVersion and Salesforce.ProfileId convenience functions were added -(#421 Not merged yet) - -Email and Username are based on FirstName and LastName if available (#420 Not merged yet) +(#421) Snowfakery now has voluminous documentation about Fakes in many languages and locales (#409) From 0c95a554bf088ee1a212e26ef27f6c2cef46d9f9 Mon Sep 17 00:00:00 2001 From: Paul Prescod Date: Wed, 7 Jul 2021 12:10:15 -0700 Subject: [PATCH 50/53] Dependency Update --- requirements/dev.txt | 16 ++++++++-------- requirements/prod.txt | 8 ++++---- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/requirements/dev.txt b/requirements/dev.txt index a351d585..f672e435 100644 --- a/requirements/dev.txt +++ b/requirements/dev.txt @@ -38,7 +38,7 @@ docopt==0.6.2 # via coveralls faker-microservice==2.0.0 # via -r requirements/dev.in -faker==8.8.1 +faker==8.10.0 # via # -r requirements/prod.txt # faker-microservice @@ -66,7 +66,7 @@ immutables==0.15 # via # -r requirements/prod.txt # contextvars -importlib-metadata==4.5.0 +importlib-metadata==4.6.1 # via # -r requirements/prod.txt # flake8 @@ -102,7 +102,7 @@ mypy-extensions==0.4.3 # via black nodeenv==1.6.0 # via pre-commit -packaging==20.9 +packaging==21.0 # via # mkdocs # pytest @@ -150,7 +150,7 @@ pyyaml==5.4.1 # pre-commit # pyyaml-env-tag # vcrpy -regex==2021.4.4 +regex==2021.7.6 # via black requests==2.25.1 # via @@ -166,7 +166,7 @@ six==1.16.0 # tox # vcrpy # virtualenv -sqlalchemy==1.4.18 +sqlalchemy==1.4.20 # via -r requirements/prod.txt text-unidecode==1.3 # via @@ -196,7 +196,7 @@ typing-extensions==3.10.0.0 # importlib-metadata # pydantic # yarl -urllib3==1.26.5 +urllib3==1.26.6 # via # requests # responses @@ -208,13 +208,13 @@ virtualenv==20.4.7 # via # pre-commit # tox -watchdog==2.1.2 +watchdog==2.1.3 # via mkdocs wrapt==1.12.1 # via vcrpy yarl==1.6.3 # via vcrpy -zipp==3.4.1 +zipp==3.5.0 # via # -r requirements/prod.txt # importlib-metadata diff --git a/requirements/prod.txt b/requirements/prod.txt index a23d94da..8b18daca 100644 --- a/requirements/prod.txt +++ b/requirements/prod.txt @@ -8,7 +8,7 @@ click==7.1.2 # via -r requirements/prod.in contextvars==2.4 # via -r requirements/prod.in -faker==8.8.1 +faker==8.10.0 # via -r requirements/prod.in greenlet==1.1.0 # via sqlalchemy @@ -16,7 +16,7 @@ gvgen==1.0 # via -r requirements/prod.in immutables==0.15 # via contextvars -importlib-metadata==4.5.0 +importlib-metadata==4.6.1 # via sqlalchemy jinja2==2.11.3 # via -r requirements/prod.in @@ -32,7 +32,7 @@ pyyaml==5.4.1 # via -r requirements/prod.in six==1.16.0 # via python-dateutil -sqlalchemy==1.4.18 +sqlalchemy==1.4.20 # via -r requirements/prod.in text-unidecode==1.3 # via faker @@ -41,5 +41,5 @@ typing-extensions==3.10.0.0 # -r requirements/prod.in # importlib-metadata # pydantic -zipp==3.4.1 +zipp==3.5.0 # via importlib-metadata From 72dad429d791f3bb09434b60aeb3dea7d9f65987 Mon Sep 17 00:00:00 2001 From: Paul Prescod Date: Wed, 7 Jul 2021 12:21:18 -0700 Subject: [PATCH 51/53] Update HISTORY.md Co-authored-by: David Reed --- HISTORY.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/HISTORY.md b/HISTORY.md index 06198755..1119a706 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -6,7 +6,7 @@ And so [Salesforce.org](http://salesforce.org/) said “Let there be data,” an ## Snowfakery 2.0 -Recipes can now merge in data from Salesforce Salesforce instances as +Recipes can now merge in data from Salesforce orgs as records, IDs or datasets. (#395 and #401) Output streams can now be specified as 3rd party libraries. Any Python classname From 0cba0da91f7483b6d88b7fd063413e9de978c530 Mon Sep 17 00:00:00 2001 From: Paul Prescod Date: Wed, 7 Jul 2021 12:21:44 -0700 Subject: [PATCH 52/53] Update HISTORY.md Co-authored-by: David Reed --- HISTORY.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/HISTORY.md b/HISTORY.md index 1119a706..2228ddb9 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -9,7 +9,7 @@ And so [Salesforce.org](http://salesforce.org/) said “Let there be data,” an Recipes can now merge in data from Salesforce orgs as records, IDs or datasets. (#395 and #401) -Output streams can now be specified as 3rd party libraries. Any Python classname +Output streams can now be specified as 3rd party libraries. Any Python class name can be passed to --output-format as long as it adheres to the OutputStream protocol as shown in examples/YamlOutputStream.py (#351) From ea87226d28cb73cac57a8bf2b7a5b277d69342db Mon Sep 17 00:00:00 2001 From: timbarton1966 Date: Fri, 9 Jul 2021 11:45:00 -0400 Subject: [PATCH 53/53] fixed/added BSD 3-Clause LICENSE file --- LICENSE | 55 +++++++++++++++++++++++++++++-------------------------- 1 file changed, 29 insertions(+), 26 deletions(-) diff --git a/LICENSE b/LICENSE index e9830463..da6962af 100644 --- a/LICENSE +++ b/LICENSE @@ -1,27 +1,30 @@ - Copyright (c) 2020, Salesforce.org - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of Salesforce.org nor the names of - its contributors may be used to endorse or promote products derived - from this software without specific prior written permission. +Copyright (c) 2021, Salesforce.com, Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the + above copyright notice, this list of conditions + and the following disclaimer. + +* Redistributions in binary form must reproduce + the above copyright notice, this list of conditions + and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of Salesforce.com nor the names + of its contributors may be used to endorse or promote + products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, +OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT +OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY +WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE.