diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 0000000..a0d4b2e
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,5 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# CodeStream ignored files
+/../../example-code\.idea/codestream.xml
diff --git a/.idea/codestream.xml b/.idea/codestream.xml
new file mode 100644
index 0000000..c9facba
--- /dev/null
+++ b/.idea/codestream.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/example-code.iml b/.idea/example-code.iml
new file mode 100644
index 0000000..d0876a7
--- /dev/null
+++ b/.idea/example-code.iml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml
new file mode 100644
index 0000000..105ce2d
--- /dev/null
+++ b/.idea/inspectionProfiles/profiles_settings.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..075f076
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..e1fe818
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..94a25f7
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Pipfile b/Pipfile
new file mode 100644
index 0000000..52a9330
--- /dev/null
+++ b/Pipfile
@@ -0,0 +1,13 @@
+[[source]]
+url = "https://pypi.org/simple"
+verify_ssl = true
+name = "pypi"
+
+[packages]
+
+[dev-packages]
+pytest = "7.1"
+assertpy = "1.1"
+
+[requires]
+python_version = "3.10"
diff --git a/Pipfile.lock b/Pipfile.lock
new file mode 100644
index 0000000..f4b6a4b
--- /dev/null
+++ b/Pipfile.lock
@@ -0,0 +1,92 @@
+{
+ "_meta": {
+ "hash": {
+ "sha256": "10cc7377c736c2d5605a4427b7303c784337f6ced936b03603db60afdf2b0968"
+ },
+ "pipfile-spec": 6,
+ "requires": {
+ "python_version": "3.10"
+ },
+ "sources": [
+ {
+ "name": "pypi",
+ "url": "https://pypi.org/simple",
+ "verify_ssl": true
+ }
+ ]
+ },
+ "default": {},
+ "develop": {
+ "assertpy": {
+ "hashes": [
+ "sha256:acc64329934ad71a3221de185517a43af33e373bb44dc05b5a9b174394ef4833"
+ ],
+ "index": "pypi",
+ "version": "==1.1"
+ },
+ "attrs": {
+ "hashes": [
+ "sha256:29e95c7f6778868dbd49170f98f8818f78f3dc5e0e37c0b1f474e3561b240836",
+ "sha256:c9227bfc2f01993c03f68db37d1d15c9690188323c067c641f1a35ca58185f99"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==22.2.0"
+ },
+ "colorama": {
+ "hashes": [
+ "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44",
+ "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"
+ ],
+ "markers": "sys_platform == 'win32'",
+ "version": "==0.4.6"
+ },
+ "exceptiongroup": {
+ "hashes": [
+ "sha256:327cbda3da756e2de031a3107b81ab7b3770a602c4d16ca618298c526f4bec1e",
+ "sha256:bcb67d800a4497e1b404c2dd44fca47d3b7a5e5433dbab67f96c1a685cdfdf23"
+ ],
+ "markers": "python_version < '3.11'",
+ "version": "==1.1.0"
+ },
+ "iniconfig": {
+ "hashes": [
+ "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3",
+ "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"
+ ],
+ "markers": "python_version >= '3.7'",
+ "version": "==2.0.0"
+ },
+ "packaging": {
+ "hashes": [
+ "sha256:714ac14496c3e68c99c29b00845f7a2b85f3bb6f1078fd9f72fd20f0570002b2",
+ "sha256:b6ad297f8907de0fa2fe1ccbd26fdaf387f5f47c7275fedf8cce89f99446cf97"
+ ],
+ "markers": "python_version >= '3.7'",
+ "version": "==23.0"
+ },
+ "pluggy": {
+ "hashes": [
+ "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159",
+ "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==1.0.0"
+ },
+ "pytest": {
+ "hashes": [
+ "sha256:c7c6ca206e93355074ae32f7403e8ea12163b1163c976fee7d4d84027c162be5",
+ "sha256:d45e0952f3727241918b8fd0f376f5ff6b301cc0777c6f9a556935c92d8a7d42"
+ ],
+ "index": "pypi",
+ "version": "==7.2.1"
+ },
+ "tomli": {
+ "hashes": [
+ "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc",
+ "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"
+ ],
+ "markers": "python_version < '3.11'",
+ "version": "==2.0.1"
+ }
+ }
+}
diff --git a/pytest.ini b/pytest.ini
new file mode 100644
index 0000000..d3f12a6
--- /dev/null
+++ b/pytest.ini
@@ -0,0 +1,4 @@
+[pytest]
+python_files = *_test.py
+python_functions = test_*
+addopts = --showlocals
diff --git a/src/__init__.py b/src/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/src/product.py b/src/product.py
new file mode 100644
index 0000000..e69de29
diff --git a/src/product_test.py b/src/product_test.py
new file mode 100644
index 0000000..cd21dd7
--- /dev/null
+++ b/src/product_test.py
@@ -0,0 +1,5 @@
+from src.testhelpers import test
+
+@test
+def foo():
+ pass
diff --git a/src/testhelpers.py b/src/testhelpers.py
new file mode 100644
index 0000000..76cdbb3
--- /dev/null
+++ b/src/testhelpers.py
@@ -0,0 +1,3 @@
+def test(f):
+ f.__test__ = True
+ return f