Skip to content

Commit b1f4e28

Browse files
committed
merge branch develop
2 parents 95ab23d + b46bfad commit b1f4e28

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

51 files changed

+1927
-60
lines changed

.codespell.skip

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
./build/pyinstaller
1818
./**/node_modules
1919
./frontend-components/**
20+
./cookiecutter/**
2021
./openbb_platform/providers/econdb/openbb_econdb/utils/helpers.py
2122
./openbb_platform/core/openbb/package/**
2223
./openbb_platform/providers/imf/openbb_imf/utils/constants.py

.coveragerc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,5 @@ omit =
44
tests/*
55
**/tests/**
66
**/package/**
7+
cookiecutter/**
78
source = .

.pylintrc

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,12 @@
11
[MASTER]
2-
2+
# Add files or directories to the blacklist. They should be base names, not
3+
# paths.
4+
ignore=CVS,cookiecutter
35
# A comma-separated list of package or module names from where C extensions may
46
# be loaded. Extensions are loading into the active Python interpreter and may
57
# run arbitrary code
68
extension-pkg-allow-list=math,binascii
79

8-
# Add files or directories to the blacklist. They should be base names, not
9-
# paths.
10-
ignore=CVS
11-
1210
# Add files or directories matching the regex patterns to the blacklist. The
1311
# regex matches against base names, not paths.
1412
ignore-patterns=

cookiecutter/MANIFEST.in

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
include README.md
2+
include LICENSE
3+
recursive-include openbb_cookiecutter/template *
4+
recursive-exclude openbb_cookiecutter/template *.pyc
5+
recursive-exclude openbb_cookiecutter/template __pycache__

cookiecutter/README.md

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
# OpenBB ODP Extensions Cookiecutter
2+
3+
[Cookiecutter](https://cookiecutter.readthedocs.io/en/1.7.2/) is a command-line utility that creates projects from templates.
4+
5+
This extension is a simple template for setting up new OpenBB Python Package extensions and projects.
6+
7+
## Template Structure
8+
9+
The Cookiecutter template prompts the user for information to use in the `pyproject.toml` file, and then generates a project based on that information.
10+
All fields are optional.
11+
12+
- Your Name
13+
- Your Email
14+
- Project Name
15+
- Project Tag (some-distributable-package)
16+
- Package Name ("include" code folder name - "some_package")
17+
- Provider Name - name of the provider for the entry point - i.e, 'fmp'
18+
- Router Name - name of the router path - i.e. `obb.{some_package}`
19+
- OBBject Name - name of the OBBject accessor namespace.
20+
21+
The template will generate all extension types as a single, installable Python project.
22+
You likely won't always use all in tandem, just delete the unwanted folders and entrypoints.
23+
24+
## Usage
25+
26+
1. Install in a Python environment from PyPI with:
27+
28+
```
29+
pip install openbb-cookiecutter
30+
```
31+
32+
Alternatively, with `uvx`:
33+
34+
```
35+
uvx openbb-cookiecutter
36+
```
37+
38+
2. Navigate the current working directory to the desired output location and run:
39+
40+
```
41+
openbb-cookiecutter
42+
```
43+
44+
Enter values or press `enter` to continue with the default.
45+
46+
3. Create a new Python environment for the project.
47+
48+
4. Navigate into the generated folder and install with:
49+
50+
```
51+
pip install -e .
52+
```
53+
54+
5. Python static files will be generated on first import, or trigger with `openbb-build`.
55+
56+
6. Import the Python package or start the API and use like any other OpenBB application.
57+
58+
7. Modify the business logic and get started building!
59+
60+
See the developer documentation [here](https://docs.openbb.co/python/developer).
61+
62+
## Contributing
63+
64+
We welcome contributions to this template! Please feel free to open an issue or submit a pull request with your improvements.
65+
66+
## Contacts
67+
68+
If you have any questions about the cookiecutter or anything OpenBB, feel free to email us at `[email protected]`
69+
70+
If you want to say hi, or are interested in partnering with us, feel free to reach us at `[email protected]`
71+
72+
Any of our social media platforms: [openbb.co/links](https://openbb.co/links)

cookiecutter/cookiecutter.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"full_name": "Super Quant",
3+
"email": "[email protected]",
4+
"project_name": "Super Quant",
5+
"project_tag": "{{ cookiecutter.project_name.lower().replace(' ', '-') }}",
6+
"package_name": "{{ cookiecutter.project_name.lower().replace(' ', '_') }}",
7+
"_template": "{% now 'utc', '%Y%m%d%H%M%S' %}"
8+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
"""OpenBB Cookiecutter Template."""
2+
3+
from pathlib import Path
4+
5+
__version__ = "0.4.0"
6+
7+
8+
def get_template_path() -> Path:
9+
"""Return the path to the cookiecutter template directory."""
10+
return Path(__file__).parent / "template"
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
"""CLI for OpenBB Cookiecutter template."""
2+
3+
# pylint: disable=W0718
4+
5+
import argparse
6+
import sys
7+
8+
from cookiecutter.main import cookiecutter
9+
10+
from . import get_template_path
11+
12+
13+
def main(argv: list | None = None) -> int:
14+
"""Run the OpenBB cookiecutter template.
15+
16+
Args:
17+
argv: Command line arguments (defaults to sys.argv[1:])
18+
19+
Returns:
20+
Exit code (0 for success, non-zero for error)
21+
"""
22+
parser = argparse.ArgumentParser(
23+
description="Generate an OpenBB Platform extension from template"
24+
)
25+
parser.add_argument(
26+
"-o",
27+
"--output-dir",
28+
default=".",
29+
help="Where to output the generated project (default: current directory)",
30+
)
31+
parser.add_argument(
32+
"--no-input",
33+
action="store_true",
34+
help="Do not prompt for parameters and use defaults",
35+
)
36+
parser.add_argument(
37+
"-f", "--overwrite-if-exists", action="store_true", help="Overwrite if exists"
38+
)
39+
parser.add_argument(
40+
"--extra-context",
41+
action="append",
42+
metavar="KEY=VALUE",
43+
help="Extra context variables (can be used multiple times)",
44+
)
45+
46+
args = parser.parse_args(argv)
47+
48+
# Build extra context from arguments
49+
extra_context = {}
50+
if args.extra_context:
51+
for item in args.extra_context:
52+
if "=" not in item:
53+
print(f"Error: extra-context must be in KEY=VALUE format: {item}")
54+
return 1
55+
key, value = item.split("=", 1)
56+
extra_context[key] = value
57+
58+
# Get the bundled template path
59+
template_path = get_template_path()
60+
61+
try:
62+
cookiecutter(
63+
str(template_path),
64+
output_dir=args.output_dir,
65+
no_input=args.no_input,
66+
overwrite_if_exists=args.overwrite_if_exists,
67+
extra_context=extra_context if extra_context else None,
68+
)
69+
return 0
70+
except Exception as e:
71+
print(f"Error: {e}", file=sys.stderr) # noqa
72+
return 1
73+
74+
75+
if __name__ == "__main__":
76+
sys.exit(main())
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"full_name": "Hello World",
3+
"email": "[email protected]",
4+
"project_name": "OpenBB Python Extension Template",
5+
"project_tag": "extension-template",
6+
"package_name": "extension_template",
7+
"provider_name": "template",
8+
"router_name": "template",
9+
"obbject_name": "template",
10+
"_template": "{% now 'utc', '%Y%m%d%H%M%S' %}"
11+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
"""OpenBB Platform Extension post-generation script."""
2+
3+
import re
4+
import sys
5+
6+
MODULE_REGEX = r"^[_a-zA-Z][_a-zA-Z0-9]+$"
7+
8+
MODULE_NAME = "{{ cookiecutter.package_name }}"
9+
PROVIDER_NAME = "{{ cookiecutter.provider_name }}" or ""
10+
ROUTER_NAME = "{{ cookiecutter.router_name }}" or ""
11+
OBBJECT_NAME = "{{ cookiecutter.obbject_name }}" or ""
12+
13+
if not re.match(MODULE_REGEX, MODULE_NAME):
14+
print(f"ERROR: {MODULE_NAME} is not a valid Python package name.")
15+
16+
sys.exit(1)
17+
18+
if PROVIDER_NAME and not re.match(MODULE_REGEX, PROVIDER_NAME):
19+
print(f"ERROR: {PROVIDER_NAME} should be in lower snakecase.")
20+
21+
sys.exit(1)
22+
23+
if ROUTER_NAME and not re.match(MODULE_REGEX, ROUTER_NAME):
24+
print(f"ERROR: {ROUTER_NAME} should be in lower snakecase.")
25+
26+
sys.exit(1)
27+
28+
if OBBJECT_NAME and not re.match(MODULE_REGEX, OBBJECT_NAME):
29+
print(f"ERROR: {OBBJECT_NAME} should be in lower snakecase.")
30+
31+
sys.exit(1)

0 commit comments

Comments
 (0)