From ea5c103677c7aeed2f4938f54c54aafb8338266f Mon Sep 17 00:00:00 2001 From: sw5556 Date: Thu, 30 Oct 2025 00:20:16 -0400 Subject: [PATCH 01/18] add banter function --- py_conversations/__init__.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 py_conversations/__init__.py diff --git a/py_conversations/__init__.py b/py_conversations/__init__.py new file mode 100644 index 0000000..ddbd8e6 --- /dev/null +++ b/py_conversations/__init__.py @@ -0,0 +1,17 @@ +import random + +__version__ = "0.1.0" + +def banter(name): + insults = [ + f"{name}, you look like you're easy to draw", + f"{name}, the closest you’ll come to a brainstorm is a light drizzle", + f"Hey {name}, You look like a “before” picture.", + f"{name}, I envy everyone who hasn’t met you", + f"Wow {name}, if ignorance is bliss, you must be ecstatic at all times.", + f"{name}, you’ll go far someday. And I hope you stay there." + f"{name}, if I gave you a penny for your thoughts, I’d get change back", + f"{name}, you look like something I drew with my left hand.", + ] + + return random.choice(insults) From f2d152ebd609d06dbc189dc101e8abaa5ba49cec Mon Sep 17 00:00:00 2001 From: Alif-4 Date: Thu, 30 Oct 2025 00:50:09 -0400 Subject: [PATCH 02/18] add conversations package skeleton --- Pipfile | 14 ++ Pipfile.lock | 391 +++++++++++++++++++++++++++++++ README.md | 2 + src/conversations/__init__.py | 1 + src/conversations/compliments.py | 1 + src/conversations/funfacts.py | 2 + src/conversations/insults.py | 1 + src/conversations/pickuplines.py | 1 + src/conversations/smalltalk.py | 1 + tests/test_compliments.py | 1 + tests/test_funfacts.py | 1 + tests/test_insults.py | 1 + tests/test_pickuplines.py | 1 + tests/test_smalltalk.py | 1 + 14 files changed, 419 insertions(+) create mode 100644 Pipfile create mode 100644 Pipfile.lock create mode 100644 src/conversations/__init__.py create mode 100644 src/conversations/compliments.py create mode 100644 src/conversations/funfacts.py create mode 100644 src/conversations/insults.py create mode 100644 src/conversations/pickuplines.py create mode 100644 src/conversations/smalltalk.py create mode 100644 tests/test_compliments.py create mode 100644 tests/test_funfacts.py create mode 100644 tests/test_insults.py create mode 100644 tests/test_pickuplines.py create mode 100644 tests/test_smalltalk.py diff --git a/Pipfile b/Pipfile new file mode 100644 index 0000000..7902141 --- /dev/null +++ b/Pipfile @@ -0,0 +1,14 @@ +[[source]] +url = "https://pypi.org/simple" +verify_ssl = true +name = "pypi" + +[packages] + +[dev-packages] +pytest = "*" +build = "*" +twine = "*" + +[requires] +python_version = "3.12" diff --git a/Pipfile.lock b/Pipfile.lock new file mode 100644 index 0000000..c184bfa --- /dev/null +++ b/Pipfile.lock @@ -0,0 +1,391 @@ +{ + "_meta": { + "hash": { + "sha256": "603a3aea6851c624c73daa98f7c39f1fded0d68ad8b41495b14170a10151cebe" + }, + "pipfile-spec": 6, + "requires": { + "python_version": "3.12" + }, + "sources": [ + { + "name": "pypi", + "url": "https://pypi.org/simple", + "verify_ssl": true + } + ] + }, + "default": {}, + "develop": { + "build": { + "hashes": [ + "sha256:698edd0ea270bde950f53aed21f3a0135672206f3911e0176261a31e0e07b397", + "sha256:7145f0b5061ba90a1500d60bd1b13ca0a8a4cebdd0cc16ed8adf1c0e739f43b4" + ], + "index": "pypi", + "markers": "python_version >= '3.9'", + "version": "==1.3.0" + }, + "certifi": { + "hashes": [ + "sha256:0f212c2744a9bb6de0c56639a6f68afe01ecd92d91f14ae897c4fe7bbeeef0de", + "sha256:47c09d31ccf2acf0be3f701ea53595ee7e0b8fa08801c6624be771df09ae7b43" + ], + "markers": "python_version >= '3.7'", + "version": "==2025.10.5" + }, + "charset-normalizer": { + "hashes": [ + "sha256:027f6de494925c0ab2a55eab46ae5129951638a49a34d87f4c3eda90f696b4ad", + "sha256:077fbb858e903c73f6c9db43374fd213b0b6a778106bc7032446a8e8b5b38b93", + "sha256:0a98e6759f854bd25a58a73fa88833fba3b7c491169f86ce1180c948ab3fd394", + "sha256:0d3d8f15c07f86e9ff82319b3d9ef6f4bf907608f53fe9d92b28ea9ae3d1fd89", + "sha256:0f04b14ffe5fdc8c4933862d8306109a2c51e0704acfa35d51598eb45a1e89fc", + "sha256:11d694519d7f29d6cd09f6ac70028dba10f92f6cdd059096db198c283794ac86", + "sha256:194f08cbb32dc406d6e1aea671a68be0823673db2832b38405deba2fb0d88f63", + "sha256:1bee1e43c28aa63cb16e5c14e582580546b08e535299b8b6158a7c9c768a1f3d", + "sha256:21d142cc6c0ec30d2efee5068ca36c128a30b0f2c53c1c07bd78cb6bc1d3be5f", + "sha256:2437418e20515acec67d86e12bf70056a33abdacb5cb1655042f6538d6b085a8", + "sha256:244bfb999c71b35de57821b8ea746b24e863398194a4014e4c76adc2bbdfeff0", + "sha256:2677acec1a2f8ef614c6888b5b4ae4060cc184174a938ed4e8ef690e15d3e505", + "sha256:277e970e750505ed74c832b4bf75dac7476262ee2a013f5574dd49075879e161", + "sha256:2aaba3b0819274cc41757a1da876f810a3e4d7b6eb25699253a4effef9e8e4af", + "sha256:2b7d8f6c26245217bd2ad053761201e9f9680f8ce52f0fcd8d0755aeae5b2152", + "sha256:2c9d3c380143a1fedbff95a312aa798578371eb29da42106a29019368a475318", + "sha256:3162d5d8ce1bb98dd51af660f2121c55d0fa541b46dff7bb9b9f86ea1d87de72", + "sha256:31fd66405eaf47bb62e8cd575dc621c56c668f27d46a61d975a249930dd5e2a4", + "sha256:362d61fd13843997c1c446760ef36f240cf81d3ebf74ac62652aebaf7838561e", + "sha256:376bec83a63b8021bb5c8ea75e21c4ccb86e7e45ca4eb81146091b56599b80c3", + "sha256:44c2a8734b333e0578090c4cd6b16f275e07aa6614ca8715e6c038e865e70576", + "sha256:47cc91b2f4dd2833fddaedd2893006b0106129d4b94fdb6af1f4ce5a9965577c", + "sha256:4902828217069c3c5c71094537a8e623f5d097858ac6ca8252f7b4d10b7560f1", + "sha256:4bd5d4137d500351a30687c2d3971758aac9a19208fc110ccb9d7188fbe709e8", + "sha256:4fe7859a4e3e8457458e2ff592f15ccb02f3da787fcd31e0183879c3ad4692a1", + "sha256:542d2cee80be6f80247095cc36c418f7bddd14f4a6de45af91dfad36d817bba2", + "sha256:554af85e960429cf30784dd47447d5125aaa3b99a6f0683589dbd27e2f45da44", + "sha256:5833d2c39d8896e4e19b689ffc198f08ea58116bee26dea51e362ecc7cd3ed26", + "sha256:5947809c8a2417be3267efc979c47d76a079758166f7d43ef5ae8e9f92751f88", + "sha256:5ae497466c7901d54b639cf42d5b8c1b6a4fead55215500d2f486d34db48d016", + "sha256:5bd2293095d766545ec1a8f612559f6b40abc0eb18bb2f5d1171872d34036ede", + "sha256:5bfbb1b9acf3334612667b61bd3002196fe2a1eb4dd74d247e0f2a4d50ec9bbf", + "sha256:5cb4d72eea50c8868f5288b7f7f33ed276118325c1dfd3957089f6b519e1382a", + "sha256:5dbe56a36425d26d6cfb40ce79c314a2e4dd6211d51d6d2191c00bed34f354cc", + "sha256:5f819d5fe9234f9f82d75bdfa9aef3a3d72c4d24a6e57aeaebba32a704553aa0", + "sha256:64b55f9dce520635f018f907ff1b0df1fdc31f2795a922fb49dd14fbcdf48c84", + "sha256:6515f3182dbe4ea06ced2d9e8666d97b46ef4c75e326b79bb624110f122551db", + "sha256:65e2befcd84bc6f37095f5961e68a6f077bf44946771354a28ad434c2cce0ae1", + "sha256:6aee717dcfead04c6eb1ce3bd29ac1e22663cdea57f943c87d1eab9a025438d7", + "sha256:6b39f987ae8ccdf0d2642338faf2abb1862340facc796048b604ef14919e55ed", + "sha256:6e1fcf0720908f200cd21aa4e6750a48ff6ce4afe7ff5a79a90d5ed8a08296f8", + "sha256:74018750915ee7ad843a774364e13a3db91682f26142baddf775342c3f5b1133", + "sha256:74664978bb272435107de04e36db5a9735e78232b85b77d45cfb38f758efd33e", + "sha256:74bb723680f9f7a6234dcf67aea57e708ec1fbdf5699fb91dfd6f511b0a320ef", + "sha256:752944c7ffbfdd10c074dc58ec2d5a8a4cd9493b314d367c14d24c17684ddd14", + "sha256:778d2e08eda00f4256d7f672ca9fef386071c9202f5e4607920b86d7803387f2", + "sha256:780236ac706e66881f3b7f2f32dfe90507a09e67d1d454c762cf642e6e1586e0", + "sha256:798d75d81754988d2565bff1b97ba5a44411867c0cf32b77a7e8f8d84796b10d", + "sha256:799a7a5e4fb2d5898c60b640fd4981d6a25f1c11790935a44ce38c54e985f828", + "sha256:7a32c560861a02ff789ad905a2fe94e3f840803362c84fecf1851cb4cf3dc37f", + "sha256:7c308f7e26e4363d79df40ca5b2be1c6ba9f02bdbccfed5abddb7859a6ce72cf", + "sha256:7fa17817dc5625de8a027cb8b26d9fefa3ea28c8253929b8d6649e705d2835b6", + "sha256:81d5eb2a312700f4ecaa977a8235b634ce853200e828fbadf3a9c50bab278328", + "sha256:82004af6c302b5d3ab2cfc4cc5f29db16123b1a8417f2e25f9066f91d4411090", + "sha256:837c2ce8c5a65a2035be9b3569c684358dfbf109fd3b6969630a87535495ceaa", + "sha256:840c25fb618a231545cbab0564a799f101b63b9901f2569faecd6b222ac72381", + "sha256:8a6562c3700cce886c5be75ade4a5db4214fda19fede41d9792d100288d8f94c", + "sha256:8af65f14dc14a79b924524b1e7fffe304517b2bff5a58bf64f30b98bbc5079eb", + "sha256:8ef3c867360f88ac904fd3f5e1f902f13307af9052646963ee08ff4f131adafc", + "sha256:94537985111c35f28720e43603b8e7b43a6ecfb2ce1d3058bbe955b73404e21a", + "sha256:99ae2cffebb06e6c22bdc25801d7b30f503cc87dbd283479e7b606f70aff57ec", + "sha256:9a26f18905b8dd5d685d6d07b0cdf98a79f3c7a918906af7cc143ea2e164c8bc", + "sha256:9b35f4c90079ff2e2edc5b26c0c77925e5d2d255c42c74fdb70fb49b172726ac", + "sha256:9cd98cdc06614a2f768d2b7286d66805f94c48cde050acdbbb7db2600ab3197e", + "sha256:9d1bb833febdff5c8927f922386db610b49db6e0d4f4ee29601d71e7c2694313", + "sha256:9f7fcd74d410a36883701fafa2482a6af2ff5ba96b9a620e9e0721e28ead5569", + "sha256:a59cb51917aa591b1c4e6a43c132f0cdc3c76dbad6155df4e28ee626cc77a0a3", + "sha256:a61900df84c667873b292c3de315a786dd8dac506704dea57bc957bd31e22c7d", + "sha256:a79cfe37875f822425b89a82333404539ae63dbdddf97f84dcbc3d339aae9525", + "sha256:a8a8b89589086a25749f471e6a900d3f662d1d3b6e2e59dcecf787b1cc3a1894", + "sha256:a8bf8d0f749c5757af2142fe7903a9df1d2e8aa3841559b2bad34b08d0e2bcf3", + "sha256:a9768c477b9d7bd54bc0c86dbaebdec6f03306675526c9927c0e8a04e8f94af9", + "sha256:ac1c4a689edcc530fc9d9aa11f5774b9e2f33f9a0c6a57864e90908f5208d30a", + "sha256:af2d8c67d8e573d6de5bc30cdb27e9b95e49115cd9baad5ddbd1a6207aaa82a9", + "sha256:b435cba5f4f750aa6c0a0d92c541fb79f69a387c91e61f1795227e4ed9cece14", + "sha256:b5b290ccc2a263e8d185130284f8501e3e36c5e02750fc6b6bdeb2e9e96f1e25", + "sha256:b5d84d37db046c5ca74ee7bb47dd6cbc13f80665fdde3e8040bdd3fb015ecb50", + "sha256:b7cf1017d601aa35e6bb650b6ad28652c9cd78ee6caff19f3c28d03e1c80acbf", + "sha256:bc7637e2f80d8530ee4a78e878bce464f70087ce73cf7c1caf142416923b98f1", + "sha256:c0463276121fdee9c49b98908b3a89c39be45d86d1dbaa22957e38f6321d4ce3", + "sha256:c4ef880e27901b6cc782f1b95f82da9313c0eb95c3af699103088fa0ac3ce9ac", + "sha256:c8ae8a0f02f57a6e61203a31428fa1d677cbe50c93622b4149d5c0f319c1d19e", + "sha256:ca5862d5b3928c4940729dacc329aa9102900382fea192fc5e52eb69d6093815", + "sha256:cb01158d8b88ee68f15949894ccc6712278243d95f344770fa7593fa2d94410c", + "sha256:cb6254dc36b47a990e59e1068afacdcd02958bdcce30bb50cc1700a8b9d624a6", + "sha256:cc00f04ed596e9dc0da42ed17ac5e596c6ccba999ba6bd92b0e0aef2f170f2d6", + "sha256:cd09d08005f958f370f539f186d10aec3377d55b9eeb0d796025d4886119d76e", + "sha256:cd4b7ca9984e5e7985c12bc60a6f173f3c958eae74f3ef6624bb6b26e2abbae4", + "sha256:ce8a0633f41a967713a59c4139d29110c07e826d131a316b50ce11b1d79b4f84", + "sha256:cead0978fc57397645f12578bfd2d5ea9138ea0fac82b2f63f7f7c6877986a69", + "sha256:d055ec1e26e441f6187acf818b73564e6e6282709e9bcb5b63f5b23068356a15", + "sha256:d1f13550535ad8cff21b8d757a3257963e951d96e20ec82ab44bc64aeb62a191", + "sha256:d9c7f57c3d666a53421049053eaacdd14bbd0a528e2186fcb2e672effd053bb0", + "sha256:d9e45d7faa48ee908174d8fe84854479ef838fc6a705c9315372eacbc2f02897", + "sha256:da3326d9e65ef63a817ecbcc0df6e94463713b754fe293eaa03da99befb9a5bd", + "sha256:de00632ca48df9daf77a2c65a484531649261ec9f25489917f09e455cb09ddb2", + "sha256:e1f185f86a6f3403aa2420e815904c67b2f9ebc443f045edd0de921108345794", + "sha256:e824f1492727fa856dd6eda4f7cee25f8518a12f3c4a56a74e8095695089cf6d", + "sha256:e912091979546adf63357d7e2ccff9b44f026c075aeaf25a52d0e95ad2281074", + "sha256:eaabd426fe94daf8fd157c32e571c85cb12e66692f15516a83a03264b08d06c3", + "sha256:ebf3e58c7ec8a8bed6d66a75d7fb37b55e5015b03ceae72a8e7c74495551e224", + "sha256:ecaae4149d99b1c9e7b88bb03e3221956f68fd6d50be2ef061b2381b61d20838", + "sha256:eecbc200c7fd5ddb9a7f16c7decb07b566c29fa2161a16cf67b8d068bd21690a", + "sha256:f155a433c2ec037d4e8df17d18922c3a0d9b3232a396690f17175d2946f0218d", + "sha256:f1e34719c6ed0b92f418c7c780480b26b5d9c50349e9a9af7d76bf757530350d", + "sha256:f34be2938726fc13801220747472850852fe6b1ea75869a048d6f896838c896f", + "sha256:f820802628d2694cb7e56db99213f930856014862f3fd943d290ea8438d07ca8", + "sha256:f8bf04158c6b607d747e93949aa60618b61312fe647a6369f88ce2ff16043490", + "sha256:f8e160feb2aed042cd657a72acc0b481212ed28b1b9a95c0cee1621b524e1966", + "sha256:f9d332f8c2a2fcbffe1378594431458ddbef721c1769d78e2cbc06280d8155f9", + "sha256:fa09f53c465e532f4d3db095e0c55b615f010ad81803d383195b6b5ca6cbf5f3", + "sha256:faa3a41b2b66b6e50f84ae4a68c64fcd0c44355741c6374813a800cd6695db9e", + "sha256:fd44c878ea55ba351104cb93cc85e74916eb8fa440ca7903e57575e97394f608" + ], + "markers": "python_version >= '3.7'", + "version": "==3.4.4" + }, + "colorama": { + "hashes": [ + "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", + "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5, 3.6'", + "version": "==0.4.6" + }, + "docutils": { + "hashes": [ + "sha256:9fdb771707c8784c8f2728b67cb2c691305933d68137ef95a75db5f4dfbc213d", + "sha256:b0e98d679283fc3bb0ead8a5da7f501baa632654e7056e9c5846842213d674d8" + ], + "markers": "python_version >= '3.9'", + "version": "==0.22.2" + }, + "id": { + "hashes": [ + "sha256:292cb8a49eacbbdbce97244f47a97b4c62540169c976552e497fd57df0734c1d", + "sha256:f1434e1cef91f2cbb8a4ec64663d5a23b9ed43ef44c4c957d02583d61714c658" + ], + "markers": "python_version >= '3.8'", + "version": "==1.5.0" + }, + "idna": { + "hashes": [ + "sha256:771a87f49d9defaf64091e6e6fe9c18d4833f140bd19464795bc32d966ca37ea", + "sha256:795dafcc9c04ed0c1fb032c2aa73654d8e8c5023a7df64a53f39190ada629902" + ], + "markers": "python_version >= '3.8'", + "version": "==3.11" + }, + "iniconfig": { + "hashes": [ + "sha256:c76315c77db068650d49c5b56314774a7804df16fee4402c1f19d6d15d8c4730", + "sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12" + ], + "markers": "python_version >= '3.10'", + "version": "==2.3.0" + }, + "jaraco.classes": { + "hashes": [ + "sha256:47a024b51d0239c0dd8c8540c6c7f484be3b8fcf0b2d85c13825780d3b3f3acd", + "sha256:f662826b6bed8cace05e7ff873ce0f9283b5c924470fe664fff1c2f00f581790" + ], + "markers": "python_version >= '3.8'", + "version": "==3.4.0" + }, + "jaraco.context": { + "hashes": [ + "sha256:9bae4ea555cf0b14938dc0aee7c9f32ed303aa20a3b73e7dc80111628792d1b3", + "sha256:f797fc481b490edb305122c9181830a3a5b76d84ef6d1aef2fb9b47ab956f9e4" + ], + "markers": "python_version >= '3.8'", + "version": "==6.0.1" + }, + "jaraco.functools": { + "hashes": [ + "sha256:227ff8ed6f7b8f62c56deff101545fa7543cf2c8e7b82a7c2116e672f29c26e8", + "sha256:cfd13ad0dd2c47a3600b439ef72d8615d482cedcff1632930d6f28924d92f294" + ], + "markers": "python_version >= '3.9'", + "version": "==4.3.0" + }, + "keyring": { + "hashes": [ + "sha256:0b39998aa941431eb3d9b0d4b2460bc773b9df6fed7621c2dfb291a7e0187a66", + "sha256:552a3f7af126ece7ed5c89753650eec89c7eaae8617d0aa4d9ad2b75111266bd" + ], + "markers": "python_version >= '3.9'", + "version": "==25.6.0" + }, + "markdown-it-py": { + "hashes": [ + "sha256:87327c59b172c5011896038353a81343b6754500a08cd7a4973bb48c6d578147", + "sha256:cb0a2b4aa34f932c007117b194e945bd74e0ec24133ceb5bac59009cda1cb9f3" + ], + "markers": "python_version >= '3.10'", + "version": "==4.0.0" + }, + "mdurl": { + "hashes": [ + "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", + "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba" + ], + "markers": "python_version >= '3.7'", + "version": "==0.1.2" + }, + "more-itertools": { + "hashes": [ + "sha256:52d4362373dcf7c52546bc4af9a86ee7c4579df9a8dc268be0a2f949d376cc9b", + "sha256:f638ddf8a1a0d134181275fb5d58b086ead7c6a72429ad725c67503f13ba30bd" + ], + "markers": "python_version >= '3.9'", + "version": "==10.8.0" + }, + "nh3": { + "hashes": [ + "sha256:0f454ba4c6aabafcaae964ae6f0a96cecef970216a57335fabd229a265fbe007", + "sha256:1de5c1a35bed19a1b1286bab3c3abfe42e990a8a6c4ce9bb9ab4bde49107ea3b", + "sha256:22b9e9c9eda497b02b7273b79f7d29e1f1170d2b741624c1b8c566aef28b1f48", + "sha256:2cb6d9e192fbe0d451c7cb1350dadedbeae286207dbf101a28210193d019752e", + "sha256:38b4872499ab15b17c5c6e9f091143d070d75ddad4a4d1ce388d043ca556629c", + "sha256:42e426f36e167ed29669b77ae3c4b9e185e4a1b130a86d7c3249194738a1d7b2", + "sha256:474b176124c1b495ccfa1c20f61b7eb83ead5ecccb79ab29f602c148e8378489", + "sha256:48425995d37880281b467f7cf2b3218c1f4750c55bcb1ff4f47f2320a2bb159c", + "sha256:489ca5ecd58555c2865701e65f614b17555179e71ecc76d483b6f3886b813a9b", + "sha256:4a2434668f4eef4eab17c128e565ce6bea42113ce10c40b928e42c578d401800", + "sha256:5a25662b392b06f251da6004a1f8a828dca7f429cd94ac07d8a98ba94d644438", + "sha256:669a908706cd28203d9cfce2f567575686e364a1bc6074d413d88d456066f743", + "sha256:670f18b09f75c86c3865f79543bf5acd4bbe2a5a4475672eef2399dd8cdb69d2", + "sha256:6a854480058683d60bdc7f0456105092dae17bef1f300642856d74bd4201da93", + "sha256:80dc7563a2a3b980e44b221f69848e3645bbf163ab53e3d1add4f47b26120355", + "sha256:8f600ad86114df21efc4a3592faa6b1d099c0eebc7e018efebb1c133376097da", + "sha256:94292dd1bd2a2e142fa5bb94c0ee1d84433a5d9034640710132da7e0376fca3a", + "sha256:a3e810a92fb192373204456cac2834694440af73d749565b4348e30235da7f0b", + "sha256:a5721f59afa0ab3dcaa0d47e58af33a5fcd254882e1900ee4a8968692a40f79d", + "sha256:b0d6c834d3c07366ecbdcecc1f4804c5ce0a77fa52ee4653a2a26d2d909980ea", + "sha256:b222c05ae5139320da6caa1c5aed36dd0ee36e39831541d9b56e048a63b4d701", + "sha256:b74bbd047b361c0f21d827250c865ff0895684d9fcf85ea86131a78cfa0b835b", + "sha256:c0acef923a1c3a2df3ee5825ea79c149b6748c6449781c53ab6923dc75e87d26", + "sha256:d7431b2a39431017f19cd03144005b6c014201b3e73927c05eab6ca37bb1d98c", + "sha256:dd6d1be301123a9af3263739726eeeb208197e5e78fc4f522408c50de77a5354", + "sha256:eaba26591867f697cffdbc539faddeb1d75a36273f5bfe957eb421d3f87d7da1" + ], + "markers": "python_version >= '3.8'", + "version": "==0.3.1" + }, + "packaging": { + "hashes": [ + "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484", + "sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f" + ], + "markers": "python_version >= '3.8'", + "version": "==25.0" + }, + "pluggy": { + "hashes": [ + "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3", + "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746" + ], + "markers": "python_version >= '3.9'", + "version": "==1.6.0" + }, + "pygments": { + "hashes": [ + "sha256:636cb2477cec7f8952536970bc533bc43743542f70392ae026374600add5b887", + "sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b" + ], + "markers": "python_version >= '3.8'", + "version": "==2.19.2" + }, + "pyproject-hooks": { + "hashes": [ + "sha256:1e859bd5c40fae9448642dd871adf459e5e2084186e8d2c2a79a824c970da1f8", + "sha256:9e5c6bfa8dcc30091c74b0cf803c81fdd29d94f01992a7707bc97babb1141913" + ], + "markers": "python_version >= '3.7'", + "version": "==1.2.0" + }, + "pytest": { + "hashes": [ + "sha256:86c0d0b93306b961d58d62a4db4879f27fe25513d4b969df351abdddb3c30e01", + "sha256:872f880de3fc3a5bdc88a11b39c9710c3497a547cfa9320bc3c5e62fbf272e79" + ], + "index": "pypi", + "markers": "python_version >= '3.9'", + "version": "==8.4.2" + }, + "pywin32-ctypes": { + "hashes": [ + "sha256:8a1513379d709975552d202d942d9837758905c8d01eb82b8bcc30918929e7b8", + "sha256:d162dc04946d704503b2edc4d55f3dba5c1d539ead017afa00142c38b9885755" + ], + "markers": "python_version >= '3.6'", + "version": "==0.2.3" + }, + "readme-renderer": { + "hashes": [ + "sha256:2fbca89b81a08526aadf1357a8c2ae889ec05fb03f5da67f9769c9a592166151", + "sha256:8712034eabbfa6805cacf1402b4eeb2a73028f72d1166d6f5cb7f9c047c5d1e1" + ], + "markers": "python_version >= '3.9'", + "version": "==44.0" + }, + "requests": { + "hashes": [ + "sha256:2462f94637a34fd532264295e186976db0f5d453d1cdd31473c85a6a161affb6", + "sha256:dbba0bac56e100853db0ea71b82b4dfd5fe2bf6d3754a8893c3af500cec7d7cf" + ], + "markers": "python_version >= '3.9'", + "version": "==2.32.5" + }, + "requests-toolbelt": { + "hashes": [ + "sha256:7681a0a3d047012b5bdc0ee37d7f8f07ebe76ab08caeccfc3921ce23c88d5bc6", + "sha256:cccfdd665f0a24fcf4726e690f65639d272bb0637b9b92dfd91a5568ccf6bd06" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==1.0.0" + }, + "rfc3986": { + "hashes": [ + "sha256:50b1502b60e289cb37883f3dfd34532b8873c7de9f49bb546641ce9cbd256ebd", + "sha256:97aacf9dbd4bfd829baad6e6309fa6573aaf1be3f6fa735c8ab05e46cecb261c" + ], + "markers": "python_version >= '3.7'", + "version": "==2.0.0" + }, + "rich": { + "hashes": [ + "sha256:73ff50c7c0c1c77c8243079283f4edb376f0f6442433aecb8ce7e6d0b92d1fe4", + "sha256:76bc51fe2e57d2b1be1f96c524b890b816e334ab4c1e45888799bfaab0021edd" + ], + "markers": "python_full_version >= '3.8.0'", + "version": "==14.2.0" + }, + "twine": { + "hashes": [ + "sha256:418ebf08ccda9a8caaebe414433b0ba5e25eb5e4a927667122fbe8f829f985d8", + "sha256:e5ed0d2fd70c9959770dce51c8f39c8945c574e18173a7b81802dab51b4b75cf" + ], + "index": "pypi", + "markers": "python_version >= '3.9'", + "version": "==6.2.0" + }, + "urllib3": { + "hashes": [ + "sha256:3fc47733c7e419d4bc3f6b3dc2b4f890bb743906a30d56ba4a5bfa4bbff92760", + "sha256:e6b01673c0fa6a13e374b50871808eb3bf7046c4b125b216f6bf1cc604cff0dc" + ], + "markers": "python_version >= '3.9'", + "version": "==2.5.0" + } + } +} diff --git a/README.md b/README.md index 6022e0e..e2635fe 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,5 @@ # Python Package Exercise +[Mahabub Alif](https://github.com/Alif-4) + An exercise to create a Python package, build it, test it, distribute it, and use it. See [instructions](./instructions.md) for details. diff --git a/src/conversations/__init__.py b/src/conversations/__init__.py new file mode 100644 index 0000000..eb4fd21 --- /dev/null +++ b/src/conversations/__init__.py @@ -0,0 +1 @@ +# Ignore for now; we will import functions as we write them. \ No newline at end of file diff --git a/src/conversations/compliments.py b/src/conversations/compliments.py new file mode 100644 index 0000000..f9bf1ab --- /dev/null +++ b/src/conversations/compliments.py @@ -0,0 +1 @@ +#TODO diff --git a/src/conversations/funfacts.py b/src/conversations/funfacts.py new file mode 100644 index 0000000..2fc89e4 --- /dev/null +++ b/src/conversations/funfacts.py @@ -0,0 +1,2 @@ +# Fun Facts function +# Implement functions that return fun facts. diff --git a/src/conversations/insults.py b/src/conversations/insults.py new file mode 100644 index 0000000..503fa1d --- /dev/null +++ b/src/conversations/insults.py @@ -0,0 +1 @@ +#TODO \ No newline at end of file diff --git a/src/conversations/pickuplines.py b/src/conversations/pickuplines.py new file mode 100644 index 0000000..503fa1d --- /dev/null +++ b/src/conversations/pickuplines.py @@ -0,0 +1 @@ +#TODO \ No newline at end of file diff --git a/src/conversations/smalltalk.py b/src/conversations/smalltalk.py new file mode 100644 index 0000000..503fa1d --- /dev/null +++ b/src/conversations/smalltalk.py @@ -0,0 +1 @@ +#TODO \ No newline at end of file diff --git a/tests/test_compliments.py b/tests/test_compliments.py new file mode 100644 index 0000000..503fa1d --- /dev/null +++ b/tests/test_compliments.py @@ -0,0 +1 @@ +#TODO \ No newline at end of file diff --git a/tests/test_funfacts.py b/tests/test_funfacts.py new file mode 100644 index 0000000..d02794b --- /dev/null +++ b/tests/test_funfacts.py @@ -0,0 +1 @@ +#Unit tests for funfacts function in Conversations module \ No newline at end of file diff --git a/tests/test_insults.py b/tests/test_insults.py new file mode 100644 index 0000000..503fa1d --- /dev/null +++ b/tests/test_insults.py @@ -0,0 +1 @@ +#TODO \ No newline at end of file diff --git a/tests/test_pickuplines.py b/tests/test_pickuplines.py new file mode 100644 index 0000000..503fa1d --- /dev/null +++ b/tests/test_pickuplines.py @@ -0,0 +1 @@ +#TODO \ No newline at end of file diff --git a/tests/test_smalltalk.py b/tests/test_smalltalk.py new file mode 100644 index 0000000..503fa1d --- /dev/null +++ b/tests/test_smalltalk.py @@ -0,0 +1 @@ +#TODO \ No newline at end of file From db7c20418c678395bfafda608100e6202827ac43 Mon Sep 17 00:00:00 2001 From: sw5556 Date: Thu, 30 Oct 2025 15:29:49 -0400 Subject: [PATCH 03/18] renamed to banter.py --- src/conversations/{insults.py => banter.py} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/conversations/{insults.py => banter.py} (100%) diff --git a/src/conversations/insults.py b/src/conversations/banter.py similarity index 100% rename from src/conversations/insults.py rename to src/conversations/banter.py From dcbc97578bc1cdadccc99aca6fd1b33337429d40 Mon Sep 17 00:00:00 2001 From: sw5556 Date: Thu, 30 Oct 2025 15:33:16 -0400 Subject: [PATCH 04/18] renamed to test_banter.py --- src/conversations/banter.py | 21 ++++++++++++++++++++- tests/{test_insults.py => test_banter.py} | 0 2 files changed, 20 insertions(+), 1 deletion(-) rename tests/{test_insults.py => test_banter.py} (100%) diff --git a/src/conversations/banter.py b/src/conversations/banter.py index 503fa1d..ddf5ede 100644 --- a/src/conversations/banter.py +++ b/src/conversations/banter.py @@ -1 +1,20 @@ -#TODO \ No newline at end of file +#TODO + +import random + +def banter(name): + + insults = [ + f"{name}, you're so bright, you make the sun look like a nightlight!", + f"Nice try, {name}. I've seen better attempts from a broken calculator.", + f"{name}, you're proof that even participation trophies have standards.", + f"Hey {name}, I'd agree with you but then we'd both be wrong.", + f"{name}, you're like a software update—nobody asked for you, but here you are anyway.", + f"Wow {name}, that idea is almost as good as pineapple on pizza.", + f"{name}, you're the reason the gene pool needs a lifeguard.", + f"Keep talking, {name}. I always yawn when I'm interested.", + f"{name}; you just have bad luck thinking.", + f"I'd challenge you to a battle of wits, {name}, but I see you came unarmed." + ] + + return random.choice(insults) \ No newline at end of file diff --git a/tests/test_insults.py b/tests/test_banter.py similarity index 100% rename from tests/test_insults.py rename to tests/test_banter.py From d48d09be48b079342ee459db08fd0c8199bfcc44 Mon Sep 17 00:00:00 2001 From: sw5556 Date: Thu, 30 Oct 2025 15:51:37 -0400 Subject: [PATCH 05/18] worked on banter.py --- src/conversations/banter.py | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/src/conversations/banter.py b/src/conversations/banter.py index ddf5ede..ee8c04b 100644 --- a/src/conversations/banter.py +++ b/src/conversations/banter.py @@ -3,18 +3,17 @@ import random def banter(name): - insults = [ - f"{name}, you're so bright, you make the sun look like a nightlight!", - f"Nice try, {name}. I've seen better attempts from a broken calculator.", - f"{name}, you're proof that even participation trophies have standards.", - f"Hey {name}, I'd agree with you but then we'd both be wrong.", - f"{name}, you're like a software update—nobody asked for you, but here you are anyway.", - f"Wow {name}, that idea is almost as good as pineapple on pizza.", - f"{name}, you're the reason the gene pool needs a lifeguard.", - f"Keep talking, {name}. I always yawn when I'm interested.", - f"{name}; you just have bad luck thinking.", - f"I'd challenge you to a battle of wits, {name}, but I see you came unarmed." + f"{name}, you look like you're easy to draw", + f"{name}, the closest you'll come to a brainstorm is a light drizzle", + f"Hey {name}, you look like a 'before' picture.", + f"{name}, I envy everyone who hasn't met you", + f"Wow {name}, if ignorance is bliss, you must be ecstatic at all times.", + f"{name}, you'll go far someday. And I hope you stay there.", + f"{name}, if I gave you a penny for your thoughts, I'd get change back", + f"{name}, you look like something I drew with my left hand." + f"{name}, you're secret is safe with me, because I wasn't listening.", + f"{name}, You bring joy to every room you exit.", ] return random.choice(insults) \ No newline at end of file From 4a268ee6390258c91151d38c97bc491a08282e4a Mon Sep 17 00:00:00 2001 From: sen5217 Date: Sun, 2 Nov 2025 16:10:44 -0500 Subject: [PATCH 06/18] add smallTalk function and tests --- README.md | 1 + src/conversations/smalltalk.py | 48 +++++++++++++++++++++++++++++++++- tests/test_smalltalk.py | 27 ++++++++++++++++++- 3 files changed, 74 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index e2635fe..63d5bcf 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,6 @@ # Python Package Exercise [Mahabub Alif](https://github.com/Alif-4) +[Sydney Nadeau](https://github.com/sen5217) An exercise to create a Python package, build it, test it, distribute it, and use it. See [instructions](./instructions.md) for details. diff --git a/src/conversations/smalltalk.py b/src/conversations/smalltalk.py index 503fa1d..3e07ef6 100644 --- a/src/conversations/smalltalk.py +++ b/src/conversations/smalltalk.py @@ -1 +1,47 @@ -#TODO \ No newline at end of file +# Small Talk function +# Implement function that returns small talk. + +import random + +questions = [ + "How's your day going?", + "What's your favorite color?", + "What's your favorite programming language?", + "I’m running purely on caffeine today — you?", + "Do you usually listen to music when you work?", + "What’s your go-to comfort show or movie?", + "I’ve been meaning to start reading/watching something new — any recommendations?", + "What do you like to do outside of school/work?", + "Do you have any hobbies you’ve picked up recently?", + "What kind of music are you into?", + "Are you more of an introvert or extrovert?", + "If you could travel anywhere right now, where would you go?", + "What’s a random skill you wish you had?", + "What’s your comfort food?", + "Do you like podcasts or audiobooks?", + "Are you a cat person, dog person, or both?", + "Anything fun or random happen to you today?" +] + +comments = [ + "The weather is nice today.", + "I’m convinced every day this week has been Tuesday.", + "I need a nap.", + "It’s one of those days where coffee feels more like a necessity than a choice.", + "My brain clocked out hours ago.", + "People who can wake up early and be nice about it scare me a little.", + "Socks with sandals are just misunderstood geniuses.", + "Avocado toast is overrated, but I’d still eat it.", + "Pineapple on pizza is disgusting.", + "I hate vegetables.", + "Movies are boring.", + "'The Office' isn't funny." +] + + +def smallTalk(question): + if question: + return random.choice(questions) + return random.choice(comments) + + diff --git a/tests/test_smalltalk.py b/tests/test_smalltalk.py index 503fa1d..727eeb3 100644 --- a/tests/test_smalltalk.py +++ b/tests/test_smalltalk.py @@ -1 +1,26 @@ -#TODO \ No newline at end of file +# Unit tests for smallTalk function in Conversations module + +from src.conversations.smalltalk import smallTalk, questions, comments + +def test_smallTalk_returns_string(): + actualQuestion = smallTalk(True) + actualComment = smallTalk(False) + + assert isinstance(actualQuestion, str), f"Expected smallTalk(True) to return a string. It instead returned {actualQuestion}" + assert isinstance(actualComment, str), f"Expected smallTalk(False) to return a string. It instead returned {actualComment}" + +def test_questions(): + actual = smallTalk(True) + assert actual in questions, f"Expected a question from the questions list, got {actual}" + +def test_comments(): + actual = smallTalk(False) + assert actual in comments, f"Expected a question from the questions list, got {actual}" + +def test_smallTalk_randomness_questions(): + chosen = set(smallTalk(True) for i in range(50)) + assert len(chosen) > 1 + +def test_smallTalk_randomness_comments(): + chosen = set(smallTalk(False) for i in range(50)) + assert len(chosen) > 1 \ No newline at end of file From 50642bb6d2cfb54a427895d959a8302f8ca8aff1 Mon Sep 17 00:00:00 2001 From: Alif-4 Date: Sun, 2 Nov 2025 19:39:10 -0500 Subject: [PATCH 07/18] Funfacts feature, add CLI flags, and pyproject.toml --- Pipfile | 1 + Pipfile.lock | 10 ++++-- pyproject.toml | 22 ++++++++++++++ src/conversations/__init__.py | 5 ++- src/conversations/__main__.py | 15 +++++++++ src/conversations/funfacts.py | 57 +++++++++++++++++++++++++++++++++-- tests/test_funfacts.py | 14 ++++++++- 7 files changed, 118 insertions(+), 6 deletions(-) create mode 100644 pyproject.toml create mode 100644 src/conversations/__main__.py diff --git a/Pipfile b/Pipfile index 7902141..843e901 100644 --- a/Pipfile +++ b/Pipfile @@ -4,6 +4,7 @@ verify_ssl = true name = "pypi" [packages] +conversations = {file = ".", editable = true} [dev-packages] pytest = "*" diff --git a/Pipfile.lock b/Pipfile.lock index c184bfa..55962a0 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "603a3aea6851c624c73daa98f7c39f1fded0d68ad8b41495b14170a10151cebe" + "sha256": "f574eba2055a008025b696e546aa6d77e2208e44b1619c59b17e8b7b794ec27b" }, "pipfile-spec": 6, "requires": { @@ -15,7 +15,13 @@ } ] }, - "default": {}, + "default": { + "conversations": { + "editable": true, + "file": ".", + "markers": "python_version >= '3.11'" + } + }, "develop": { "build": { "hashes": [ diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..eecec6a --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,22 @@ +[build-system] +requires = ["setuptools>=68", "wheel"] +build-backend = "setuptools.build_meta" + +[project] +name = "conversations" +version = "0.0.1" +description = "Lighthearted conversation helpers (fun facts, etc.)" +requires-python = ">=3.9" +authors = [{name="Team Mistral"}] + +[project.scripts] +conversations = "conversations.__main__:main" + +[tool.setuptools.package-dir] +"" = "src" + +[tool.setuptools.packages.find] +where = ["src"] + +[tool.pytest.ini_options] +pythonpath = ["src"] diff --git a/src/conversations/__init__.py b/src/conversations/__init__.py index eb4fd21..e45de0a 100644 --- a/src/conversations/__init__.py +++ b/src/conversations/__init__.py @@ -1 +1,4 @@ -# Ignore for now; we will import functions as we write them. \ No newline at end of file +from .funfacts import fun_fact + +__all__ = ["fun_fact"] # append your function to this list +__version__ = "0.0.1" diff --git a/src/conversations/__main__.py b/src/conversations/__main__.py new file mode 100644 index 0000000..3d5d794 --- /dev/null +++ b/src/conversations/__main__.py @@ -0,0 +1,15 @@ +from .funfacts import fun_fact +import argparse + +def main() -> None: + parser = argparse.ArgumentParser(prog="conversations") + parser.add_argument("--category", default="general") + parser.add_argument("--rarity", default="common") + args = parser.parse_args() + + #add your function parsing strateg here for CLI + + print(fun_fact(category=args.category, rarity=args.rarity)) + +if __name__ == "__main__": + main() diff --git a/src/conversations/funfacts.py b/src/conversations/funfacts.py index 2fc89e4..e8f5cab 100644 --- a/src/conversations/funfacts.py +++ b/src/conversations/funfacts.py @@ -1,2 +1,55 @@ -# Fun Facts function -# Implement functions that return fun facts. +import random + +#data +FACTS = { + "general": { + "common": [ + "Bananas are berries, but strawberries aren’t.", + "Octopuses have three hearts.", + ], + "rare": [ + "Sharks existed before trees.", + "Honey never spoils—it can last for millennia.", + ], + }, + "science": { + "common": [ + "A day on Venus is longer than a year on Venus.", + "Humans share about 60% of their DNA with bananas.", + ], + "rare": [ + "Water can boil and freeze at the same time (triple point).", + "There are more stars in the universe than grains of sand on Earth.", + ], + }, + "history": { + "common": [ + "Oxford University predates the Aztec Empire.", + "Cleopatra lived closer to us than to the building of the pyramids.", + ], + "rare": [ + "Ancient Roman concrete can 'self-heal'.", + "The first computer bug was a real moth (1947).", + ], + }, + "animals": { + "common": [ + "A group of flamingos is called a flamboyance.", + "Cows can have best friends.", + ], + "rare": [ + "Axolotls can regenerate parts of their brain.", + "Some jellyfish can revert to a juvenile state.", + ], + }, +} + + +def fun_fact(category: str = "general", rarity: str = "common") -> str: + """ + Return one fun fact. + Falls back to general and common if inputs are unknown. + """ + cat = FACTS.get(category) or FACTS["general"] + pool = cat.get(rarity) or cat["common"] + return random.choice(pool) diff --git a/tests/test_funfacts.py b/tests/test_funfacts.py index d02794b..95b611c 100644 --- a/tests/test_funfacts.py +++ b/tests/test_funfacts.py @@ -1 +1,13 @@ -#Unit tests for funfacts function in Conversations module \ No newline at end of file +from conversations.funfacts import fun_fact, FACTS + +def test_returns_string_nonempty(): + s = fun_fact() + assert isinstance(s, str) and s.strip() + +def test_fallback_on_unknown_inputs(): + s = fun_fact(category="???", rarity="???") + assert isinstance(s, str) and s.strip() + +def test_member_of_requested_pool(): + s = fun_fact("science", "rare") + assert s in FACTS["science"]["rare"] From 17d6a820984d9288bb5e20143e2d788ab3a630f9 Mon Sep 17 00:00:00 2001 From: sen5217 Date: Sun, 2 Nov 2025 22:15:31 -0500 Subject: [PATCH 08/18] Fixed test_smalltalk import, added CLI flags for smalltalk --- src/conversations/__init__.py | 3 ++- src/conversations/__main__.py | 8 ++++++++ tests/test_smalltalk.py | 2 +- 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/conversations/__init__.py b/src/conversations/__init__.py index e45de0a..a761236 100644 --- a/src/conversations/__init__.py +++ b/src/conversations/__init__.py @@ -1,4 +1,5 @@ from .funfacts import fun_fact +from .smalltalk import smallTalk -__all__ = ["fun_fact"] # append your function to this list +__all__ = ["fun_fact", "smallTalk"] # append your function to this list __version__ = "0.0.1" diff --git a/src/conversations/__main__.py b/src/conversations/__main__.py index 3d5d794..d18cb92 100644 --- a/src/conversations/__main__.py +++ b/src/conversations/__main__.py @@ -1,15 +1,23 @@ from .funfacts import fun_fact +from .smalltalk import smallTalk import argparse def main() -> None: parser = argparse.ArgumentParser(prog="conversations") parser.add_argument("--category", default="general") parser.add_argument("--rarity", default="common") + + parser.add_argument("--question", action="store_true") + parser.add_argument("--comment", action="store_true") + args = parser.parse_args() #add your function parsing strateg here for CLI print(fun_fact(category=args.category, rarity=args.rarity)) + + if args.question or args.comment: + print(smallTalk(args.question)) if __name__ == "__main__": main() diff --git a/tests/test_smalltalk.py b/tests/test_smalltalk.py index 727eeb3..90d0b8d 100644 --- a/tests/test_smalltalk.py +++ b/tests/test_smalltalk.py @@ -1,6 +1,6 @@ # Unit tests for smallTalk function in Conversations module -from src.conversations.smalltalk import smallTalk, questions, comments +from conversations.smalltalk import smallTalk, questions, comments def test_smallTalk_returns_string(): actualQuestion = smallTalk(True) From 09f733c03c420843c4963efe21a23f2ecd864d31 Mon Sep 17 00:00:00 2001 From: yungsemitone Date: Mon, 3 Nov 2025 13:10:33 -0500 Subject: [PATCH 09/18] added pickup lines function and tests --- src/conversations/pickuplines.py | 43 +++++++++++++++++++++++++++++++- tests/test_pickuplines.py | 25 ++++++++++++++++++- tests/test_smalltalk.py | 2 +- 3 files changed, 67 insertions(+), 3 deletions(-) diff --git a/src/conversations/pickuplines.py b/src/conversations/pickuplines.py index 503fa1d..10b901f 100644 --- a/src/conversations/pickuplines.py +++ b/src/conversations/pickuplines.py @@ -1 +1,42 @@ -#TODO \ No newline at end of file +import random + +PICKUPLINES = { + "classic": [ + "you have a great smile.", + "you make the room feel brighter.", + "your kindness stands out.", + "you have awesome energy.", + ], + "poetic": [ + "your presence feels like morning sunshine.", + "your laugh sounds like a good song.", + "you carry a little bit of starlight with you.", + "you’re a calm breeze on a warm day.", + ], + "funny": [ + "you’re the human version of the ‘skip intro’ button, instantly great.", + "your vibe is like perfect wifi, I feel a connection.", + "you’re meme-worthy in the best way.", + "you’re plot-armor for bad moods.", + ], + "nerdy": [ + "you’re a clean solution in a messy codebase.", + "your curiosity has amazing test coverage.", + "you’re big-O of awesome: constant impact.", + "you’re a well-documented feature of the universe.", + ], +} + +def pickUpLine(kind, name=""): + """ + Returns a compliment + kind is required, name is optional + """ + if kind not in PICKUPLINES: + raise ValueError("unknown kind (use classic, poetic, funny, nerdy)") + + line = random.choice(PICKUPLINES[kind]) + + if name: + return f"{name}, {line}" + return line diff --git a/tests/test_pickuplines.py b/tests/test_pickuplines.py index 503fa1d..732a220 100644 --- a/tests/test_pickuplines.py +++ b/tests/test_pickuplines.py @@ -1 +1,24 @@ -#TODO \ No newline at end of file +from conversations.pickuplines import pickUpLine, PICKUPLINES + +def test_pickUpLine_returns_string(): + actual_no_name = pickUpLine("classic") + actual_with_name = pickUpLine("poetic", "Aden") + assert isinstance(actual_no_name, str), f"Expected a string, got {actual_no_name}" + assert isinstance(actual_with_name, str), f"Expected a string, got {actual_with_name}" + +def test_member_of_requested_pool_no_name(): + actual = pickUpLine("funny") + assert actual in PICKUPLINES["funny"], f"Expected a funny pick up line, got {actual}" + +def test_member_of_requested_pool_with_name(): + actual = pickUpLine("nerdy", "Sam") + base = actual.replace("Sam, ", "") + assert base in PICKUPLINES["nerdy"], f"Expected a nerdy pick up line, got {actual}" + +def test_name_prefix_when_provided(): + actual = pickUpLine("classic", "Taylor") + assert actual.startswith("Taylor, "), f"Expected 'Taylor, (pick up line)', got {actual}" + +def test_randomness_over_multiple_calls(): + chosen = set(pickUpLine("poetic") for _ in range(50)) + assert len(chosen) > 1 diff --git a/tests/test_smalltalk.py b/tests/test_smalltalk.py index 727eeb3..90d0b8d 100644 --- a/tests/test_smalltalk.py +++ b/tests/test_smalltalk.py @@ -1,6 +1,6 @@ # Unit tests for smallTalk function in Conversations module -from src.conversations.smalltalk import smallTalk, questions, comments +from conversations.smalltalk import smallTalk, questions, comments def test_smallTalk_returns_string(): actualQuestion = smallTalk(True) From 0fcf3b287f0edb4814027a5dadef6d91a557157f Mon Sep 17 00:00:00 2001 From: yungsemitone Date: Mon, 3 Nov 2025 14:21:09 -0500 Subject: [PATCH 10/18] added init and main for pickupline function --- src/conversations/__init__.py | 3 ++- src/conversations/__main__.py | 3 +++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/conversations/__init__.py b/src/conversations/__init__.py index a761236..55250d8 100644 --- a/src/conversations/__init__.py +++ b/src/conversations/__init__.py @@ -1,5 +1,6 @@ from .funfacts import fun_fact from .smalltalk import smallTalk +from .pickuplines import pickUpLine -__all__ = ["fun_fact", "smallTalk"] # append your function to this list +__all__ = ["fun_fact", "smallTalk", "pickUpLine"] # append your function to this list __version__ = "0.0.1" diff --git a/src/conversations/__main__.py b/src/conversations/__main__.py index d18cb92..865aaec 100644 --- a/src/conversations/__main__.py +++ b/src/conversations/__main__.py @@ -9,6 +9,9 @@ def main() -> None: parser.add_argument("--question", action="store_true") parser.add_argument("--comment", action="store_true") + + parser.add_argument("--kind") + parser.add_argument("--name", default="") args = parser.parse_args() From 62af42d09288f714c4dff3e500d04ca57a069026 Mon Sep 17 00:00:00 2001 From: yungsemitone Date: Mon, 3 Nov 2025 14:25:43 -0500 Subject: [PATCH 11/18] fixed default issue --- src/conversations/__main__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/conversations/__main__.py b/src/conversations/__main__.py index 865aaec..1382197 100644 --- a/src/conversations/__main__.py +++ b/src/conversations/__main__.py @@ -11,7 +11,7 @@ def main() -> None: parser.add_argument("--comment", action="store_true") parser.add_argument("--kind") - parser.add_argument("--name", default="") + parser.add_argument("--name") args = parser.parse_args() From bf82fad6c2dd895abf4adc797c2c4519848127cb Mon Sep 17 00:00:00 2001 From: Serena Wang Date: Mon, 3 Nov 2025 11:47:12 -0800 Subject: [PATCH 12/18] Add compliments function and tests --- src/conversations/compliments.py | 104 +++++++++++++++++++++++++++++++ tests/test_compliments.py | 87 ++++++++++++++++++++++++++ 2 files changed, 191 insertions(+) diff --git a/src/conversations/compliments.py b/src/conversations/compliments.py index f9bf1ab..9ee1517 100644 --- a/src/conversations/compliments.py +++ b/src/conversations/compliments.py @@ -1 +1,105 @@ +import random +from typing import Optional, Literal + +Intensity = Literal[1, 2, 3] +Style = Literal["classic", "geeky", "poetic"] +Category = Literal["personality", "appearance", "accomplishment", "specific"] + +def compliment( + name: str = "", + intensity: Intensity = 1, + style: Style = "classic", + category: Category = "personality", + detail: Optional[str] = None, +) -> str: + intensity = 1 if intensity < 1 else 3 if intensity > 3 else intensity + + base = { + "personality": { + 1: [ + "You're such a thoughtful person.", + "You have a gift for making others feel valued.", + "I appreciate your honesty.", + ], + 2: [ + "Your confidence is inspiring.", + "Your kindness is contagious.", + "You have an amazing sense of humor.", + ], + 3: [ + "Your presence lifts everyone around you.", + "Your integrity and empathy set the standard.", + "Your strength under pressure is remarkable.", + ], + }, + "appearance": { + 1: [ + "I love your sense of style.", + "That color looks great on you.", + "You look great today.", + ], + 2: [ + "Your outfit is on point.", + "You always add something unique to your look.", + "Your smile lights up the room.", + ], + 3: [ + "Your look today is stunning.", + "Your style is effortlessly impressive.", + "You have a standout, polished presence.", + ], + }, + "accomplishment": { + 1: [ + "I admire your creativity.", + "You're a considerate, dependable team player.", + "You have a real way with words.", + ], + 2: [ + "You're an exceptional problem-solver.", + "Your ideas are fresh and insightful.", + "You structure complex tasks brilliantly.", + ], + 3: [ + "Your work sets a new bar for quality.", + "Your leadership on tough tasks is outstanding.", + "You consistently turn hard problems into clear wins.", + ], + }, + "specific": { + 1: [ + "I was really impressed by {detail}.", + "Your thoughtful approach to {detail} stood out.", + ], + 2: [ + "The way you handled {detail} showed real skill.", + "{detail} was a smart, well-judged choice.", + ], + 3: [ + "{detail} was exceptional—truly impressive.", + "Your execution on {detail} was outstanding.", + ], + }, + } + + pool = base.get(category, base["personality"])[intensity] + sentence = random.choice(pool) + + if category == "specific": + sentence = sentence.replace("{detail}", detail or "that") + + style_tail = { + "classic": "", + "geeky": " It's elegantly optimized.", + "poetic": " Like sunlight through calm water.", + }[style] + + if name: + sentence = f"{name}, {sentence}" + + banned = ["for someone like you", "than you look", "actually pretty good", "not bad", "surprisingly good"] + if any(b in sentence.lower() for b in banned): + sentence = f"{name+', ' if name else ''}You're doing great." + + return (sentence + style_tail).strip() #TODO diff --git a/tests/test_compliments.py b/tests/test_compliments.py index 503fa1d..e30ee9c 100644 --- a/tests/test_compliments.py +++ b/tests/test_compliments.py @@ -1 +1,88 @@ +import random +import pytest +from conversations.compliments import compliment + +""" +Unit tests for compliment(). +""" + +@pytest.fixture(autouse=True) +def _seed_each_test(): + # Ensure repeatable outputs for tests that rely on random.choice + random.seed(0) + + +def test_returns_nonempty_string(): + result = compliment() + assert isinstance(result, str) + assert result.strip() != "" + + +def test_name_prefix_present_when_provided(): + s = compliment("Serena", intensity=2) + assert s.startswith("Serena, ") + + +def test_intensity_is_clamped_to_1_3_bounds(): + low = compliment(intensity=0) # below lower bound -> clamp to 1 + high = compliment(intensity=99) # above upper bound -> clamp to 3 + assert isinstance(low, str) and isinstance(high, str) + assert low.strip() != "" and high.strip() != "" + + +@pytest.mark.parametrize( + "style, tail_check", + [ + ("classic", lambda s: not s.endswith("optimized.") and "calm water." not in s), + ("geeky", lambda s: s.endswith("optimized.")), + ("poetic", lambda s: s.endswith("calm water.")), + ], +) +def test_style_tails(style, tail_check): + s = compliment(style=style) + assert tail_check(s) + + +@pytest.mark.parametrize("category", ["personality", "appearance", "accomplishment"]) +def test_all_standard_categories_return_strings(category): + s = compliment(category=category, intensity=2) + assert isinstance(s, str) + assert s.strip() != "" + + +def test_specific_category_without_detail_uses_placeholder(): + s = compliment(category="specific", intensity=1) + assert "that" in s.lower() + + +def test_specific_category_with_detail_is_injected(): + s = compliment(category="specific", detail="your presentation", intensity=2) + assert "your presentation" in s + + +def test_invalid_category_falls_back_gracefully(): + s = compliment(category="not-a-real-category") + assert isinstance(s, str) and s.strip() != "" + + +def test_backhanded_fragments_are_filtered_out(): + banned = [ + "for someone like you", + "than you look", + "actually pretty good", + "not bad", + "surprisingly good", + ] + s = compliment() + assert not any(b in s.lower() for b in banned) + + +def test_accepts_none_name_without_crashing(): + s = compliment(name=None) + assert isinstance(s, str) and s.strip() != "" + + +def test_output_is_single_line_no_newlines(): + s = compliment() + assert "\n" not in s and "\r" not in s #TODO \ No newline at end of file From 8eeabf9b15e3179f55f3ba5b3321f9ccd4b51088 Mon Sep 17 00:00:00 2001 From: sw5556 Date: Mon, 3 Nov 2025 21:42:48 -0500 Subject: [PATCH 13/18] Update README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 63d5bcf..49a430b 100644 --- a/README.md +++ b/README.md @@ -2,5 +2,7 @@ [Mahabub Alif](https://github.com/Alif-4) [Sydney Nadeau](https://github.com/sen5217) +[Susan Wang](https://github.com/sw5556) + An exercise to create a Python package, build it, test it, distribute it, and use it. See [instructions](./instructions.md) for details. From 14d3c549a31d46846d0086c9d22b7c4937c548cd Mon Sep 17 00:00:00 2001 From: yungsemitone Date: Mon, 3 Nov 2025 21:47:16 -0500 Subject: [PATCH 14/18] fixed main for pickup and added to ReadMe --- README.md | 2 +- src/conversations/__main__.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 49a430b..7418860 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,6 @@ [Mahabub Alif](https://github.com/Alif-4) [Sydney Nadeau](https://github.com/sen5217) [Susan Wang](https://github.com/sw5556) - +[Aden Juda](https://github.com/yungsemitone) An exercise to create a Python package, build it, test it, distribute it, and use it. See [instructions](./instructions.md) for details. diff --git a/src/conversations/__main__.py b/src/conversations/__main__.py index e6ff546..a1a41db 100644 --- a/src/conversations/__main__.py +++ b/src/conversations/__main__.py @@ -12,8 +12,8 @@ def main() -> None: parser.add_argument("--question", action="store_true") parser.add_argument("--comment", action="store_true") - parser.add_argument("--kind") - parser.add_argument("--name") + parser.add_argument("--kind", choices=["classic", "poetic", "funny", "nerdy"]) + parser.add_argument("--name", default = "") # banter.py parser.add_argument("--intensity", choices=["mild", "medium", "intense"]) From 7fe09ecdfc669a71fbe97c5dfb70a9b3f63ba91f Mon Sep 17 00:00:00 2001 From: sen5217 Date: Mon, 3 Nov 2025 23:34:40 -0500 Subject: [PATCH 15/18] Adding fixes to __main__.py and testing build.yaml badge --- .github/workflows/build.yaml | 43 ++++++++++++++++++++++++++++++ .github/workflows/event-logger.yml | 2 +- Pipfile.lock | 2 +- README.md | 4 +++ src/conversations/__main__.py | 3 ++- tests/test_smalltalk.py | 3 +++ 6 files changed, 54 insertions(+), 3 deletions(-) create mode 100644 .github/workflows/build.yaml diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml new file mode 100644 index 0000000..3aa6b39 --- /dev/null +++ b/.github/workflows/build.yaml @@ -0,0 +1,43 @@ +name: CI / CD +on: + pull_request: + push: + branches: pipfile-experiment +jobs: + build: + runs-on: ubuntu-latest + timeout-minutes: 5 + strategy: + matrix: + python-version: ["3.9", "3.11"] + steps: + - uses: actions/checkout@v4 + - name: Install Python, pipenv and Pipfile packages + uses: kojoru/prepare-pipenv@v1 + with: + python-version: ${{ matrix.python-version }} + - name: Turn on 'editable' mode + run: | + pipenv install -e . + - name: Test with pytest + run: | + pipenv install pytest + pipenv --venv + pipenv run python -m pytest + deliver: + needs: [build] + runs-on: ubuntu-latest + timeout-minutes: 5 + steps: + - uses: actions/checkout@v4 + - name: Install Python, pipenv and Pipfile packages + uses: kojoru/prepare-pipenv@v1 + - name: Build package + run: | + pipenv install build + pipenv run python -m build . + - name: Publish to PyPI test server + uses: pypa/gh-action-pypi-publish@release/v1 + with: + password: ${{ secrets.TEST_PYPI_API_TOKEN }} + repository-url: https://test.pypi.org/legacy/ \ No newline at end of file diff --git a/.github/workflows/event-logger.yml b/.github/workflows/event-logger.yml index 31f231e..bf5f731 100644 --- a/.github/workflows/event-logger.yml +++ b/.github/workflows/event-logger.yml @@ -1,5 +1,5 @@ name: log github events -on: +on: push: branches: [main, master, pipfile-experiment] pull_request: diff --git a/Pipfile.lock b/Pipfile.lock index 3503457..11ff713 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "81f656ce820abdd745962c33c078c5c7b95af78b9d4a2bc6381cda97a7161959" + "sha256": "1b13d5a983804281ff8b1670cab7d07b64f7a9c5d5fa35de78ccb20de9dc1a21" }, "pipfile-spec": 6, "requires": { diff --git a/README.md b/README.md index 7418860..db4a23c 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,12 @@ # Python Package Exercise +![CI / CD](https://github.com/swe-students-fall2025/3-python-package-team_mistral/actions/workflows/build.yaml/badge.svg) [Mahabub Alif](https://github.com/Alif-4) + [Sydney Nadeau](https://github.com/sen5217) + [Susan Wang](https://github.com/sw5556) + [Aden Juda](https://github.com/yungsemitone) An exercise to create a Python package, build it, test it, distribute it, and use it. See [instructions](./instructions.md) for details. diff --git a/src/conversations/__main__.py b/src/conversations/__main__.py index a1a41db..8bc7ac4 100644 --- a/src/conversations/__main__.py +++ b/src/conversations/__main__.py @@ -9,6 +9,7 @@ def main() -> None: parser.add_argument("--category", default="general") parser.add_argument("--rarity", default="common") + parser.add_argument("--smalltalk", action="store_true") parser.add_argument("--question", action="store_true") parser.add_argument("--comment", action="store_true") @@ -25,7 +26,7 @@ def main() -> None: print(fun_fact(category=args.category, rarity=args.rarity)) - if args.question or args.comment: + if args.smalltalk: print(smallTalk(args.question)) if args.banter: diff --git a/tests/test_smalltalk.py b/tests/test_smalltalk.py index 90d0b8d..c097b65 100644 --- a/tests/test_smalltalk.py +++ b/tests/test_smalltalk.py @@ -2,6 +2,7 @@ from conversations.smalltalk import smallTalk, questions, comments +# Correct return type test def test_smallTalk_returns_string(): actualQuestion = smallTalk(True) actualComment = smallTalk(False) @@ -9,6 +10,7 @@ def test_smallTalk_returns_string(): assert isinstance(actualQuestion, str), f"Expected smallTalk(True) to return a string. It instead returned {actualQuestion}" assert isinstance(actualComment, str), f"Expected smallTalk(False) to return a string. It instead returned {actualComment}" +# Correct return (question or comment) based on input tests def test_questions(): actual = smallTalk(True) assert actual in questions, f"Expected a question from the questions list, got {actual}" @@ -17,6 +19,7 @@ def test_comments(): actual = smallTalk(False) assert actual in comments, f"Expected a question from the questions list, got {actual}" +# Sufficient coverage of questions/comments tests def test_smallTalk_randomness_questions(): chosen = set(smallTalk(True) for i in range(50)) assert len(chosen) > 1 From f760ddfe3bf71c4945338c8f74bf3933941d2d41 Mon Sep 17 00:00:00 2001 From: sw5556 Date: Mon, 3 Nov 2025 23:39:27 -0500 Subject: [PATCH 16/18] updated banter.py --- src/conversations/banter.py | 4 +--- tests/test_banter.py | 42 +++---------------------------------- 2 files changed, 4 insertions(+), 42 deletions(-) diff --git a/src/conversations/banter.py b/src/conversations/banter.py index 7a2100e..66fcb08 100644 --- a/src/conversations/banter.py +++ b/src/conversations/banter.py @@ -34,9 +34,7 @@ def banter(intensity, name=""): Returns a playful insult. intensity is required (use mild, medium, or intense), name is optional. """ - if intensity not in insults: - raise ValueError(f"Invalid intensity '{intensity}'. Choose 'mild', 'medium', or 'intense'.") - + # Remove the if statement - let Python raise KeyError naturally result = random.choice(insults[intensity]) if name: diff --git a/tests/test_banter.py b/tests/test_banter.py index 5cbb3f4..e7457fe 100644 --- a/tests/test_banter.py +++ b/tests/test_banter.py @@ -4,47 +4,11 @@ class TestBanter: - # Basic functionality tests - def test_returns_string(self): - """Verify banter returns a non-empty string.""" - for intensity in ["mild", "medium", "intense"]: - result = banter(intensity) - assert isinstance(result, str), f"Expected string, got {type(result)}" - assert len(result) > 0, "Expected non-empty string" - - def test_multiple_calls_vary(self): - """Verify banter returns different results across multiple calls.""" - results = [banter("mild") for _ in range(20)] - assert len(set(results)) >= 2, "Expected variation in output" - - def test_output_is_lowercase(self): - """Verify insults start with lowercase letter.""" - result = banter("medium") - assert result[0].islower(), "Expected insult to start with lowercase" - - # Name parameter tests - def test_name_appears_in_output(self): - """Check that provided name appears in the result.""" - name = "Alice" - result = banter("mild", name) - assert name in result, f"Expected '{name}' in output" - - def test_name_at_start_with_comma(self): - """Verify name formatting starts with 'Name,'.""" - name = "Bob" - result = banter("intense", name) - assert result.startswith(f"{name},"), f"Expected '{name},' at start" - - def test_no_name_no_comma(self): - """Verify output without name doesn't start with comma.""" - result = banter("medium") - assert not result.startswith(","), "Shouldn't start with comma" - # Intensity level tests def test_mild_intensity_works(self): mild_keywords = ["penny", "drizzle", "software", "secret", "loading"] found = False - for _ in range(30): + for _ in range(15): if any(word in banter("mild").lower() for word in mild_keywords): found = True break @@ -54,7 +18,7 @@ def test_medium_intensity_works(self): """Test medium intensity returns appropriate content.""" medium_keywords = ["envy", "far someday", "left hand", "participation", "exit"] found = False - for _ in range(30): + for _ in range(15): if any(word in banter("medium").lower() for word in medium_keywords): found = True break @@ -64,7 +28,7 @@ def test_intense_intensity_works(self): """Test intense intensity returns corresponding content.""" intense_keywords = ["cloud", "bad luck", "lost", "tree", "monday", "before picture"] found = False - for _ in range(30): + for _ in range(15): if any(word in banter("intense").lower() for word in intense_keywords): found = True break From cfc7eb085596fce3bd045cb5cf4641afe75af4be Mon Sep 17 00:00:00 2001 From: sen5217 Date: Mon, 3 Nov 2025 23:57:09 -0500 Subject: [PATCH 17/18] Adding fixes to __main__.py and testing build.yaml badge after test_banter.py fixes --- src/conversations/banter.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/conversations/banter.py b/src/conversations/banter.py index 66fcb08..99c164d 100644 --- a/src/conversations/banter.py +++ b/src/conversations/banter.py @@ -34,7 +34,6 @@ def banter(intensity, name=""): Returns a playful insult. intensity is required (use mild, medium, or intense), name is optional. """ - # Remove the if statement - let Python raise KeyError naturally result = random.choice(insults[intensity]) if name: From 6e8f9ca2dbf05b2e95d88d5e72bd740b716e4a66 Mon Sep 17 00:00:00 2001 From: yungsemitone Date: Tue, 4 Nov 2025 08:26:27 -0500 Subject: [PATCH 18/18] added parsing argument for pickup --- src/conversations/__main__.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/conversations/__main__.py b/src/conversations/__main__.py index 8bc7ac4..ea8e6d3 100644 --- a/src/conversations/__main__.py +++ b/src/conversations/__main__.py @@ -1,6 +1,7 @@ from .funfacts import fun_fact from .smalltalk import smallTalk from .banter import banter +from .pickuplines import pickUpLine import argparse @@ -33,6 +34,9 @@ def main() -> None: intensity = args.intensity if args.intensity else "medium" name = args.name if args.name else "" print(banter(intensity, name)) + + if args.pickup and args.kind: + print(pickUpLine(args.kind, args.name)) if __name__ == "__main__": main()