-
-
Notifications
You must be signed in to change notification settings - Fork 82
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Refactor config #485
Comments
Here's the PR! #516.⚡ Sweep Basic Tier: I'm using GPT-4. You have 4 GPT-4 tickets left for the month and 2 for the day.
For more GPT-4 tickets, visit our payment portal. For a one week free trial, try Sweep Pro (unlimited GPT-4 tickets). Actions (click)
Sandbox Execution ✓Here are the sandbox execution logs prior to making any changes: Sandbox logs for
|
script_location = alembic | |
# template used to generate migration file names; The default value is %%(rev)s_%%(slug)s | |
# Uncomment the line below if you want the files to be prepended with date and time | |
# see https://alembic.sqlalchemy.org/en/latest/tutorial.html#editing-the-ini-file | |
# for all available tokens | |
# file_template = %%(year)d_%%(month).2d_%%(day).2d_%%(hour).2d%%(minute).2d-%%(rev)s_%%(slug)s | |
# sys.path path, will be prepended to sys.path if present. | |
# defaults to the current working directory. | |
prepend_sys_path = . | |
# timezone to use when rendering the date within the migration file | |
# as well as the filename. | |
# If specified, requires the python-dateutil library that can be | |
# installed by adding `alembic[tz]` to the pip requirements | |
# string value is passed to dateutil.tz.gettz() | |
# leave blank for localtime | |
# timezone = | |
# max length of characters to apply to the | |
# "slug" field | |
# truncate_slug_length = 40 | |
# set to 'true' to run the environment during | |
# the 'revision' command, regardless of autogenerate | |
# revision_environment = false | |
# set to 'true' to allow .pyc and .pyo files without | |
# a source .py file to be detected as revisions in the | |
# versions/ directory | |
# sourceless = false | |
# version location specification; This defaults | |
# to alembic/versions. When using multiple version | |
# directories, initial revisions must be specified with --version-path. | |
# The path separator used here should be the separator specified by "version_path_separator" below. | |
# version_locations = %(here)s/bar:%(here)s/bat:alembic/versions | |
# version path separator; As mentioned above, this is the character used to split | |
# version_locations. The default within new alembic.ini files is "os", which uses os.pathsep. | |
# If this key is omitted entirely, it falls back to the legacy behavior of splitting on spaces and/or commas. | |
# Valid values for version_path_separator are: | |
# | |
# version_path_separator = : | |
# version_path_separator = ; | |
# version_path_separator = space | |
version_path_separator = os # Use os.pathsep. Default configuration used for new projects. | |
# the output encoding used when revision files | |
# are written from script.py.mako | |
# output_encoding = utf-8 | |
sqlalchemy.url = driver://user:pass@localhost/dbname | |
[post_write_hooks] | |
# post_write_hooks defines scripts or Python functions that are run | |
# on newly generated revision scripts. See the documentation for further | |
# detail and examples | |
# format using "black" - use the console_scripts runner, against the "black" entrypoint | |
# hooks = black | |
# black.type = console_scripts | |
# black.entrypoint = black | |
# black.options = -l 79 REVISION_SCRIPT_FILENAME |
Lines 87 to 224 in 5708256
# 'US_SSN', | |
# 'MEDICAL_LICENSE' | |
], | |
"SCRUB_KEYS_HTML": [ | |
"text", | |
"canonical_text", | |
"title", | |
"state", | |
"task_description", | |
"key_char", | |
"canonical_key_char", | |
"key_vk", | |
"children", | |
], | |
"PLOT_PERFORMANCE": True, | |
# VISUALIZATION CONFIGURATIONS | |
"VISUALIZE_DARK_MODE": False, | |
"VISUALIZE_RUN_NATIVELY": True, | |
"VISUALIZE_DENSE_TREES": True, | |
"VISUALIZE_ANIMATIONS": True, | |
"VISUALIZE_EXPAND_ALL": False, # not recommended for large trees | |
"VISUALIZE_MAX_TABLE_CHILDREN": 10, | |
# Calculate and save the difference between 2 neighboring screenshots | |
"SAVE_SCREENSHOT_DIFF": False, | |
"SPACY_MODEL_NAME": "en_core_web_trf", | |
"PRIVATE_AI_API_KEY": "<set your api key in .env>", | |
} | |
# each string in STOP_STRS should only contain strings | |
# that don't contain special characters | |
STOP_STRS = [ | |
"oa.stop", | |
# TODO: | |
# "<ctrl>+c,<ctrl>+c,<ctrl>+c" | |
] | |
# each list in SPECIAL_CHAR_STOP_SEQUENCES should contain sequences | |
# containing special chars, separated by keys | |
SPECIAL_CHAR_STOP_SEQUENCES = [["ctrl", "ctrl", "ctrl"]] | |
# sequences that when typed, will stop the recording of ActionEvents in record.py | |
STOP_SEQUENCES = [ | |
list(stop_str) for stop_str in STOP_STRS | |
] + SPECIAL_CHAR_STOP_SEQUENCES | |
ENV_FILE_PATH = ".env" | |
def getenv_fallback(var_name: str) -> str: | |
"""Get the value of an environment variable or fallback to the default value. | |
Args: | |
var_name (str): The name of the environment variable. | |
Returns: | |
The value of the environment variable or the fallback default value. | |
Raises: | |
ValueError: If the environment variable is not defined. | |
""" | |
rval = os.getenv(var_name) or _DEFAULTS.get(var_name) | |
if type(rval) is str and rval.lower() in ( | |
"true", | |
"false", | |
"1", | |
"0", | |
): | |
rval = rval.lower() == "true" or rval == "1" | |
if type(rval) is str and rval.isnumeric(): | |
rval = int(rval) | |
if rval is None: | |
raise ValueError(f"{var_name=} not defined") | |
return rval | |
def persist_env(var_name: str, val: str, env_file_path: str = ENV_FILE_PATH) -> None: | |
"""Persist an environment variable to a .env file. | |
Args: | |
var_name (str): The name of the environment variable. | |
val (str): The value of the environment variable. | |
env_file_path (str, optional): The path to the .env file (default: ".env"). | |
""" | |
if not os.path.exists(env_file_path): | |
with open(env_file_path, "w") as f: | |
f.write(f"{var_name}={val}") | |
else: | |
# find and replace | |
with open(env_file_path, "r") as f: | |
lines = f.readlines() | |
for i, line in enumerate(lines): | |
if line.startswith(f"{var_name}="): | |
lines[i] = f"{var_name}={val}\n" | |
break | |
else: | |
# we didn't find the variable in the file, so append it | |
if lines[-1][-1] != "\n": | |
lines.append("\n") | |
lines.append(f"{var_name}={val}") | |
with open(env_file_path, "w") as f: | |
f.writelines(lines) | |
load_dotenv() | |
for key in _DEFAULTS: | |
val = getenv_fallback(key) | |
locals()[key] = val | |
ROOT_DIRPATH = pathlib.Path(__file__).parent.parent.resolve() | |
DB_FPATH = ROOT_DIRPATH / DB_FNAME # type: ignore # noqa | |
DB_URL = f"sqlite:///{DB_FPATH}" | |
DIRNAME_PERFORMANCE_PLOTS = "performance" | |
def obfuscate(val: str, pct_reveal: float = 0.1, char: str = "*") -> str: | |
"""Obfuscates a value by replacing a portion of characters. | |
Args: | |
val (str): The value to obfuscate. | |
pct_reveal (float, optional): Percentage of characters to reveal (default: 0.1). | |
char (str, optional): Obfuscation character (default: "*"). | |
Returns: | |
str: Obfuscated value with a portion of characters replaced. | |
Raises: | |
AssertionError: If length of obfuscated value does not match original value. | |
""" | |
num_reveal = int(len(val) * pct_reveal) | |
num_obfuscate = len(val) - num_reveal | |
obfuscated = char * num_obfuscate | |
revealed = val[-num_reveal:] | |
rval = f"{obfuscated}{revealed}" | |
assert len(rval) == len(val), (val, rval) | |
return rval | |
_OBFUSCATE_KEY_PARTS = ("KEY", "PASSWORD", "TOKEN") | |
if multiprocessing.current_process().name == "MainProcess": |
Lines 1 to 40 in 5708256
# How to contribute | |
We would love to implement your contributions to this project! We simply ask that you observe the following guidelines. | |
## Code Style | |
This project follows the [Google Python Style Guide](https://google.github.io/styleguide/pyguide.html), | |
with the following modifications: | |
- imports are ordered first by group (in order of built-in, external, local), then lexicographically | |
- import groups are separated by newlines | |
For example: | |
``` | |
# built-in | |
from functools import partial | |
from pprint import pformat | |
import json | |
# external | |
from loguru import logger | |
import numpy as np | |
# local | |
from openadapt import models | |
``` | |
## Creating Issues | |
In order to effectively communicate any bugs or request new features, please select the appropriate form. If none of the options suit your needs, you can click on "Open a blank issue" located at the bottom. | |
## Testing | |
[GitHub Actions](https://github.com/MLDSAI/OpenAdapt/actions/new) are automatically run on each pull request to ensure consistent behavior and style. The Actions are composed of PyTest, [black](https://github.com/psf/black) and [flake8](https://flake8.pycqa.org/en/latest/user/index.html). | |
You can run these tests on your own computer by downloading the dependencies using `poetry` (see [here](https://github.com/OpenAdaptAI/OpenAdapt/blob/main/README.md#install)) and then running `pytest` in the root directory. | |
## Pull Request Format | |
To speed up the review process, please use the provided pull request template and create a draft pull request to get initial feedback. | |
The pull request template includes areas to explain the changes, and a checklist with boxes for code style, testing, and documentation. | |
Step 2: ⌨️ Coding
- Extract
openadapt/config.py
✓ 26b994e
Extract openadapt/config.py with contents:
• Extract the logic for loading variables from .env and saving defaults into separate functions.
• Replace the `_DEFAULTS` dictionary with direct variable definitions.
• Update the `getenv_fallback`, `persist_env`, and `obfuscate` functions to work with the new configuration management approach.
- Create
tests/test_config.py
✓ 210457c
Create tests/test_config.py with contents:
• Unit tests for `getenv_fallback`, `persist_env`, and `obfuscate` functions, to be written in `tests/test_config.py`.
• Test `getenv_fallback` with both existing and non-existing environment variables. Check that it returns the correct values and raises a ValueError for non-existing variables without a default value.
• Test `persist_env` with different variable names and values. Check that it correctly updates the .env file.
• Test `obfuscate` with different input values, percentages, and characters. Check that it returns the correct obfuscated values.
- Check
tests/test_config.py
✗
Sandbox logs for
trunk fmt tests/test_config.py || exit 0
1/2 ✓✔ Formatted tests/test_config.py Re-checking autofixed files... ✔ Formatted tests/test_config.py Re-checking autofixed files... Checked 1 file ✔ No issues
trunk check --fix --print-failures tests/test_config.py
2/2 ❌ (`1`)ISSUES tests/test_config.py:10:0 10:0 low Use of assert detected. The enclosed code will be removed when compiling to optimised byte bandit/B101 code. 11:0 low Use of assert detected. The enclosed code will be removed when compiling to optimised byte bandit/B101 code. 23:0 low Use of assert detected. The enclosed code will be removed when compiling to optimised byte bandit/B101 code. 27:0 low Use of assert detected. The enclosed code will be removed when compiling to optimised byte bandit/B101 code. 28:0 low Use of assert detected. The enclosed code will be removed when compiling to optimised byte bandit/B101 code. 29:0 low Use of assert detected. The enclosed code will be removed when compiling to optimised byte bandit/B101 code. Checked 1 file ✖ 6 new issues
- Modify
tests/test_config.py
! No changes made
Modify tests/test_config.py with contents:
• Replace the assert statements in the `test_getenv_fallback` function with the `pytest.raises` function for the ValueError check and the `assert` function from the pytest module for the other checks.
• Replace the assert statement in the `test_persist_env` function with the `assert` function from the pytest module.
• Replace the assert statements in the `test_obfuscate` function with the `assert` function from the pytest module.
- Check
tests/test_config.py
✗
Run `tests/test_config.py` through the sandbox.
- Check
tests/test_config.py
✗
Sandbox logs for
trunk fmt tests/test_config.py || exit 0
1/2 ✓✔ Formatted tests/test_config.py Re-checking autofixed files... ✔ Formatted tests/test_config.py Re-checking autofixed files... Checked 1 file ✔ No issues
trunk check --fix --print-failures tests/test_config.py
2/2 ❌ (`1`)ISSUES tests/test_config.py:10:0 10:0 low Use of assert detected. The enclosed code will be removed when compiling to optimised byte bandit/B101 code. 11:0 low Use of assert detected. The enclosed code will be removed when compiling to optimised byte bandit/B101 code. 23:0 low Use of assert detected. The enclosed code will be removed when compiling to optimised byte bandit/B101 code. 27:0 low Use of assert detected. The enclosed code will be removed when compiling to optimised byte bandit/B101 code. 28:0 low Use of assert detected. The enclosed code will be removed when compiling to optimised byte bandit/B101 code. 29:0 low Use of assert detected. The enclosed code will be removed when compiling to optimised byte bandit/B101 code. Checked 1 file ✖ 6 new issues
Step 3: 🔁 Code Review
I have finished reviewing the code for completeness. I did not find errors for sweep/refactor-config-management
.
🎉 Latest improvements to Sweep:
- Sweep now uses the
rope
library to refactor Python! Check out Large Language Models are Bad at Refactoring Code. To have Sweep refactor your code, trysweep: Refactor <your_file>.py to be more modular
! - Sweep finds and fixes bugs in your code by writing unit tests! Check out Having GPT-4 Iterate on Unit Tests like a Human.
💡 To recreate the pull request edit the issue title or description. To tweak the pull request, leave a comment on the pull request.
Join Our Discord
Unless there are compelling reasons otherwise, we likely want to go with Pydantic, as per #489 (comment), e.g:
|
Feature request
Currently we have:
This requires lots of linter pragmas. This task involves refactoring simply:
This will involve considering loading variables from .env and saving defaults correctly (e.g.
DEFAULTS = locals()
?)Motivation
Too many linter pragmas when using config vars
Checklist
openadapt/config.py
✓ 26b994etests/test_config.py
✓ 210457ctests/test_config.py
✗tests/test_config.py
! No changes madetests/test_config.py
✗The text was updated successfully, but these errors were encountered: