diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 000000000..39515b10f --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,62 @@ +name: build + +on: + release: + types: [ released ] + pull_request: + workflow_dispatch: + +defaults: + run: + shell: micromamba-shell {0} + +jobs: + build: + uses: OpenAstronomy/github-actions-workflows/.github/workflows/publish_pure_python.yml@v1 + with: + upload_to_pypi: ${{ (github.event_name == 'release') && (github.event.action == 'released') }} + secrets: + pypi_token: ${{ secrets.PYPI_PASSWORD_STSCI_MAINTAINER }} + freeze: + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: + [ "ubuntu-latest", "macos-latest" ] + python-version: + [ "3.11", "3.12" ] + fail-fast: false + name: freeze versions (Python ${{ matrix.python-version }}, ${{ matrix.os }}) + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + - uses: mamba-org/setup-micromamba@v1 + with: + environment-name: jwql-${{ runner.os }}-py${{ matrix.python-version }} + environment-file: environment.yml + create-args: >- + python=${{ matrix.python-version }} + conda + init-shell: none + generate-run-shell: true + - run: pip install . + - run: pip list + - id: version + uses: mtkennerly/dunamai-action@v1 + with: + args: --strict --pattern "default-unprefixed" --style semver + - id: filename + run: echo "filename=jwql_${{ steps.version.outputs.version }}_conda_${{ runner.os }}_${{ runner.arch }}_py${{ matrix.python-version }}.yml" >> $GITHUB_OUTPUT + - run: conda env export --no-build | grep -v "name:" | grep -v "prefix:" > ${{ steps.filename.outputs.filename }} + - run: cat ${{ steps.filename.outputs.filename }} + - uses: actions/upload-artifact@v4 + with: + name: ${{ steps.filename.outputs.filename }} + path: ${{ steps.filename.outputs.filename }} + - if: (github.event_name == 'release' && github.event.action == 'released') + uses: svenstaro/upload-release-action@v2 + with: + file: ${{ steps.filename.outputs.filename }} + + diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b35747ba1..f2f1727ea 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,15 +1,13 @@ -name: JWQL CI +name: test -on: [push, pull_request] +on: + push: + pull_request: concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true -defaults: - run: - shell: bash -l {0} - jobs: check: runs-on: ubuntu-latest @@ -17,7 +15,7 @@ jobs: - uses: actions/checkout@v4 - uses: actions/setup-python@v4 with: - python-version: "3.x" + python-version: "3.11" - run: pip install bandit - run: bandit ./jwql/ -c .bandit @@ -25,31 +23,38 @@ jobs: name: test (Python ${{ matrix.python-version }}, ${{ matrix.os }}) runs-on: ${{ matrix.os }} strategy: - max-parallel: 5 - fail-fast: false matrix: - os: [ubuntu-latest, macos-latest] - python-version: ["3.10"] - + os: [ "ubuntu-latest", "macos-latest" ] + python-version: [ "3.11", "3.12" ] + fail-fast: false + env: + PYTHONUNBUFFERED: 1 + defaults: + run: + shell: micromamba-shell {0} steps: - uses: actions/checkout@v4 - + - uses: mamba-org/setup-micromamba@v1 with: - environment-file: ./environment_python_${{ matrix.python-version }}.yml - cache-environment: true - cache-downloads: true - init-shell: bash + environment-name: jwql-${{ runner.os }}-py${{ matrix.python-version }} + environment-file: environment.yml + create-args: >- + python=${{ matrix.python-version }} + init-shell: none + generate-run-shell: true + + - run: pip install -e .[test] pytest-xdist - - run: pip install -e .[test] + - run: pip list - run: micromamba env export - - uses: supercharge/redis-github-action@1.4.0 + - if: runner.os == 'Linux' + uses: supercharge/redis-github-action@1.4.0 with: redis-version: 5.0 - if: runner.os == 'Linux' - run: python -c "import jwql; print('Version ' + jwql.__version__); print('Path ' + jwql.__path__[0])" - - run: pytest jwql/tests/ + - run: pytest -n auto jwql/tests/ diff --git a/.gitignore b/.gitignore index 64320a824..a6c451e08 100644 --- a/.gitignore +++ b/.gitignore @@ -19,3 +19,4 @@ jwql/website/apps/jwql/static/filesystem jwql/website/apps/jwql/static/outputs jwql/website/apps/jwql/static/preview_images jwql/website/apps/jwql/static/thumbnails +jwql-current.yml diff --git a/.readthedocs.yaml b/.readthedocs.yaml index 51ac7ef2e..82276d712 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -13,9 +13,6 @@ build: os: ubuntu-22.04 tools: python: "3.11" - jobs: - post_install: - - pip install sqlalchemy==1.4.46 # Build documentation in the docs/ directory with Sphinx sphinx: @@ -27,6 +24,7 @@ sphinx: # Optionally declare the Python requirements required to build your docs python: install: - - requirements: rtd_requirements.txt - method: pip path: . + extra_requirements: + - docs diff --git a/CHANGES.rst b/CHANGES.rst index 47c7c630b..412d75070 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -1,5 +1,46 @@ ## What's Changed +1.2.10 (2024-07-10) +=================== + +Duplicate of 1.2.9, caused by changes to versioning conflicts with pypi. + + +1.2.9 (2024-07-10) +================== + +Web Application +~~~~~~~~~~~~~~~ +- Add Download CSV button to query page by @BradleySappington in https://github.com/spacetelescope/jwql/pull/1561 +- show file anomalies on exposure group page by @BradleySappington in https://github.com/spacetelescope/jwql/pull/1564 +- create generic error page to handle exceptions in views. by @BradleySappington in https://github.com/spacetelescope/jwql/pull/1549 + +Project & API Documentation +~~~~~~~~~~~~~~~~~~~~~~~~~~~ +- final model define for faking by @BradleySappington in https://github.com/spacetelescope/jwql/pull/1544 +- Update Redis Package Names in Environment Files by @mfixstsci in https://github.com/spacetelescope/jwql/pull/1546 +- [SCSB-145] require Python 3.10 by @zacharyburnett in https://github.com/spacetelescope/jwql/pull/1515 +- debug false by default by @BradleySappington in https://github.com/spacetelescope/jwql/pull/1550 +- Update NIRSpec TA Monitors to use Django DB Models by @mfixstsci in https://github.com/spacetelescope/jwql/pull/1499 +- Update NIRSpec TA Models by @mfixstsci in https://github.com/spacetelescope/jwql/pull/1565 +- Remove codecov.yml by @bhilbert4 in https://github.com/spacetelescope/jwql/pull/1588 +- Remove filename parser test over filesystem by @bhilbert4 in https://github.com/spacetelescope/jwql/pull/1586 +- Update remote to upstream in pull_jwql_branch.sh by @bhilbert4 in https://github.com/spacetelescope/jwql/pull/1591 +- Add Dependencies for Servers in `pyproject.toml` by @mfixstsci in https://github.com/spacetelescope/jwql/pull/1568 +- fix release upload step condition to match workflow trigger by @zacharyburnett in https://github.com/spacetelescope/jwql/pull/1593 +- fix environment freeze workflow not picking up tag by @zacharyburnett in https://github.com/spacetelescope/jwql/pull/1594 +- fix version matching pattern by @zacharyburnett in https://github.com/spacetelescope/jwql/pull/1595 +- updating freeze matrix to include linux, mac and python 3.12 by @mfixstsci in https://github.com/spacetelescope/jwql/pull/1596 +- Remove P750L from list of NIRSpec filters by @bhilbert4 in https://github.com/spacetelescope/jwql/pull/1598 +- [build] fix `runs-on:` and update build filename for easier parsing by @zacharyburnett in https://github.com/spacetelescope/jwql/pull/1599 +- upload to PyPI on release by @zacharyburnett in https://github.com/spacetelescope/jwql/pull/1601 +- Updating jwst_reffiles version number by @mfixstsci in https://github.com/spacetelescope/jwql/pull/1606 +- Remove old presentations from repo by @bhilbert4 in https://github.com/spacetelescope/jwql/pull/1607 +- Num results fix by @BradleySappington in https://github.com/spacetelescope/jwql/pull/1608 +- Add Environment Update Script by @mfixstsci in https://github.com/spacetelescope/jwql/pull/1609 +- Add new NIRISS AMI-related suffixes by @bhilbert4 in https://github.com/spacetelescope/jwql/pull/1613 + + 1.2.8 (2024-04-18) ================== diff --git a/codecov.yml b/codecov.yml deleted file mode 100644 index 237a28191..000000000 --- a/codecov.yml +++ /dev/null @@ -1,36 +0,0 @@ -codecov: - notify: - require_ci_to_pass: no - -coverage: - precision: 2 - round: down - range: "0...75" - - status: - project: off - patch: off - changes: off - -parsers: - gcov: - branch_detection: - conditional: yes - loop: yes - method: no - macro: no - -comment: - layout: "header, diff, files" - behavior: default - require_changes: no - -ignore: - - "jwql/database/" - - "jwql/tests/" - - "jwql/instrument_monitors/miri_monitors/data_trending/plots/" - - "jwql/instrument_monitors/nirspec_monitors/data_trending/plots/" - - "*__init__.py*" - - "**/*.html" - - "**/*.js" - - "**/*.css" diff --git a/environment.yml b/environment.yml new file mode 100644 index 000000000..53e6986a7 --- /dev/null +++ b/environment.yml @@ -0,0 +1,3 @@ +dependencies: + - firefox + - python diff --git a/environment_python_3.10.yml b/environment_python_3.10.yml deleted file mode 100644 index fd81cbd6f..000000000 --- a/environment_python_3.10.yml +++ /dev/null @@ -1,74 +0,0 @@ -# This file describes a conda environment that can be to install jwql -# -# Run the following command to set up this environment: -# $ conda env create -f environment_python_3.10.yml -# -# The environment name can be overridden with the following command: -# $ conda env create -n -f environment_python_3.10.yml -# -# Run the following command to activate the environment: -# $ source activate jwql-3.10 -# -# To deactivate the environment run the following command: -# $ source deactivate -# -# To remove the environment entirely, run the following command: -# $ conda env remove -n jwql-3.10 - -name: jwql-3.10 - -channels: - - conda-forge - - defaults - -dependencies: - - astropy=5.3.4 - - beautifulsoup4=4.12.2 - - bokeh=3.3.0 - - celery=5.3.4 - - cryptography=41.0.4 - - django=4.2.6 - - inflection=0.5.1 - - ipython=8.16.1 - - jinja2=3.1.2 - - jsonschema=4.19.1 - - matplotlib=3.8.0 - - nodejs=20.8.0 - - numpy=1.25.2 - - numpydoc=1.5.0 - - pandas=2.1.1 - - pip=23.2.1 - - postgresql=15.4 - - psycopg2=2.9.7 - - pytest=7.4.2 - - pytest-cov=4.1.0 - - pytest-mock=3.11.1 - - python=3.10.12 - - pyyaml=6.0.1 - - redis-py=5.0.0 - - redis-server=7.2.4 - - ruff=0.0.292 - - scipy=1.9.3 - - setuptools=68.2.2 - - sphinx=7.2.6 - - sphinx_rtd_theme=1.3.0 - - sqlalchemy=2.0.21 - - twine=4.0.2 - - wtforms=3.0.1 - - - pip: - - astroquery==0.4.6 - - bandit==1.7.5 - - jwst==1.12.3 - - jwst_backgrounds==1.2.0 - - pysiaf==0.20.0 - - pysqlite3==0.5.2 - - pyvo==1.4.2 - - selenium==4.13.0 - - stdatamodels==1.8.3 - - stsci_rtd_theme==1.0.0 - - vine==5.0.0 - - git+https://github.com/spacetelescope/jwst_reffiles - - # Current package - - -e . diff --git a/jwql/install-env.sh b/jwql/install-env.sh new file mode 100644 index 000000000..130f65754 --- /dev/null +++ b/jwql/install-env.sh @@ -0,0 +1,70 @@ +branchname=$1 +python_version=$2 + +printf "UPDATING JWQL ENVIRONMENT\n\n" + +# Check operating system to obtain proper substring for environment +if [[ "$OSTYPE" == "darwin"* ]]; then + os_str="macOS_ARM64" + printf "INFORMATION: \n \t MAC OS DETECTED, USING MAC ENVIRONMENT FILE\n" +elif [[ "$OSTYPE" == "linux-gnu"* ]]; then + os_str="Linux_X64" + printf "INFORMATION: \n \t LINUX OS DETECTED, USING LINUX ENVIRONMENT FILE\n" +else + printf "EXCEPTION: \n \t $OSTYPE NOT SUPPORTED, EXITING" + return +fi + +# Check if branch name starts with "v" for our major releases +# Our branch names contain v prior to version number, but version names on git +# do not contain v prior to the number. +if [[ $branchname == v* ]]; then + jwql_version=${branchname:1:${#branchname}} + environment_url=https://github.com/spacetelescope/jwql/releases/download/$jwql_version/ + environment_name=jwql_${jwql_version}_conda_${os_str}_py${python_version} + environment_filename="${environment_name}.yml" +else + printf "EXCEPTION: \n \t RELEASE DOESNT FOLLOW RELEASE VERSIONING NAMING CONVENTION, EXITING" + return +fi + +# Download asset from release and install it. +if curl --head --silent --fail "${environment_url}${environment_filename}" 2> /dev/null; + then + # Reset back to base first before generating environment (incase one is currently activated) + eval "$(conda shell.bash deactivate)" + eval "$(conda shell.bash activate base)" + printf "\n SUCESSFULLY LOCATED ENVIRONMENT FILE ${environment_url}${environment_filename} \n" + curl -L "${environment_url}/${environment_filename}" > jwql-current.yml + $CONDA_EXE env create --name $environment_name --file jwql-current.yml + else + printf "EXCEPTION:\n" + printf "\t ${environment_url}${environment_filename} DOES NOT EXIST, EXITING\n" + printf "\t \nENSURE THAT: \n" + printf "\t https://github.com/spacetelescope/jwql/releases/tag/$branchname \n" + printf "EXISTS AND VERIFY ASSET FOR ${jwql_version}, ${python_version} FOR OS ${os_str}" + return +fi + +# Update symlink +cd ${CONDA_PREFIX}/envs/ + +env_symlink="jwql-current" + +if [[ -L $env_symlink || -e $env_symlink ]]; then + printf "INFORMATION:\n" + printf "\tjwql-current SYMLINK EXISTS, UNLINKING\n" + unlink jwql-current +fi + +printf "INFORMATION:\n\tLINKING NEW ENVIRONMENT\n" +ln -s $environment_name jwql-current + +printf "\tjwql-current HAS BEEN SET TO: ${environment_name}\n" +printf "\tTO SEE CHANGES, EXIT/RESTART SHELL\n" + +# return to original directory +cd - + +# Conda commands change shell prompt, this just returns it to the default +export PS1="\n(base)\h:\W \u\$ " diff --git a/jwql/pull_jwql_branch.sh b/jwql/pull_jwql_branch.sh index ed0dceeaa..6c4bcbf94 100644 --- a/jwql/pull_jwql_branch.sh +++ b/jwql/pull_jwql_branch.sh @@ -62,12 +62,12 @@ echo "Reset: $reset"; echo "Notify: $notify $recipient"; # 1. Pull updated code from GitHub deployment branch (keep second checkout in case its already defined for some weird reason) -git fetch origin -git checkout -b $branch_name --track origin/$branch_name +git fetch upstream +git checkout -b $branch_name --track upstream/$branch_name git checkout $branch_name -git fetch origin $branch_name -git pull origin $branch_name -git fetch origin --tags +git fetch upstream $branch_name +git pull upstream $branch_name +git fetch upstream --tags # 2. Bring the service down if [ "$reset" = true ]; then diff --git a/jwql/tests/test_utils.py b/jwql/tests/test_utils.py index ecc34790b..31bfc802c 100644 --- a/jwql/tests/test_utils.py +++ b/jwql/tests/test_utils.py @@ -430,35 +430,6 @@ def test_filename_parser(filename, solution): assert filename_parser(filename) == solution -@pytest.mark.skipif(ON_GITHUB_ACTIONS, reason='Requires access to central storage.') -def test_filename_parser_whole_filesystem(): - """Test the filename_parser on all files currently in the filesystem.""" - # Get all files - filesystem_dir = get_config()['filesystem'] - all_files = [] - for dir_name, _, file_list in os.walk(filesystem_dir): - for file in file_list: - if 'public' in file or 'proprietary' in file: - if file.endswith('.fits'): - all_files.append(os.path.join(dir_name, file)) - - # Run the filename_parser on all files - bad_filenames = [] - for filepath in all_files: - try: - filename_parser(filepath) - except ValueError: - bad_filenames.append(os.path.basename(filepath)) - - # Determine if the test failed - fail = bad_filenames != [] - failure_msg = '{} files could not be successfully parsed: \n - {}'.\ - format(len(bad_filenames), '\n - '.join(bad_filenames)) - - # Check which ones failed - assert not fail, failure_msg - - def test_filename_parser_non_jwst(): """Attempt to generate a file parameter dictionary from a file that is not formatted in the JWST naming convention. Ensure the diff --git a/jwql/utils/constants.py b/jwql/utils/constants.py index 3691d0cd8..e56d33da9 100644 --- a/jwql/utils/constants.py +++ b/jwql/utils/constants.py @@ -470,7 +470,6 @@ "F170LP", "F290LP", "OPAQUE", - "P750L", ], } @@ -786,7 +785,7 @@ ] # Possible suffix types for AMI files -NIRISS_AMI_SUFFIX_TYPES = ["amiavg", "aminorm", "ami", "psf-amiavg"] +NIRISS_AMI_SUFFIX_TYPES = ["amiavg", "aminorm", "ami", "psf-amiavg", "psf-ami-oi", "ami-oi", "aminorm-oi", "amimulti-oi", "amilg"] # Determine if the code is being run as part of CI checking on github ON_GITHUB_ACTIONS = '/home/runner' in os.path.expanduser('~') or '/Users/runner' in os.path.expanduser('~') diff --git a/jwql/utils/utils.py b/jwql/utils/utils.py index 9b6812443..9113169f5 100644 --- a/jwql/utils/utils.py +++ b/jwql/utils/utils.py @@ -530,7 +530,8 @@ def filename_parser(filename): time_series, time_series_2c, guider, - guider_segment] + guider_segment + ] filename_type_names = [ 'stage_1_and_2', diff --git a/jwql/website/apps/jwql/forms.py b/jwql/website/apps/jwql/forms.py index f9ce45b7b..90c43cafe 100644 --- a/jwql/website/apps/jwql/forms.py +++ b/jwql/website/apps/jwql/forms.py @@ -160,7 +160,7 @@ class JwqlQueryForm(BaseForm): num_choices = [(50, 50), (100, 100), (200, 200), (500, 500)] num_per_page = forms.ChoiceField( required=True, - choices=num_choices, initial=num_choices[1], + choices=num_choices, initial=num_choices[3], widget=forms.RadioSelect) # instrument specific parameters diff --git a/jwql/website/apps/jwql/views.py b/jwql/website/apps/jwql/views.py index 54cb17859..cb4c31782 100644 --- a/jwql/website/apps/jwql/views.py +++ b/jwql/website/apps/jwql/views.py @@ -131,6 +131,7 @@ def jwql_query(request): parameters[QueryConfigKeys.DATE_RANGE] = form.cleaned_data['date_range'] parameters[QueryConfigKeys.PROPOSAL_CATEGORY] = form.cleaned_data['proposal_category'] parameters[QueryConfigKeys.SORT_TYPE] = form.cleaned_data['sort_type'] + parameters[QueryConfigKeys.NUM_PER_PAGE] = form.cleaned_data['num_per_page'] parameters[QueryConfigKeys.ANOMALIES] = all_anomalies parameters[QueryConfigKeys.APERTURES] = all_apers parameters[QueryConfigKeys.FILTERS] = all_filters diff --git a/presentations/jwql_presentation.pdf b/presentations/jwql_presentation.pdf deleted file mode 100644 index 99641c67b..000000000 Binary files a/presentations/jwql_presentation.pdf and /dev/null differ diff --git a/presentations/jwql_tips_2019_07.pdf b/presentations/jwql_tips_2019_07.pdf deleted file mode 100644 index 7f83548b5..000000000 Binary files a/presentations/jwql_tips_2019_07.pdf and /dev/null differ diff --git a/presentations/jwql_web_app.pdf b/presentations/jwql_web_app.pdf deleted file mode 100644 index cb059894e..000000000 Binary files a/presentations/jwql_web_app.pdf and /dev/null differ diff --git a/pyproject.toml b/pyproject.toml index 36cb032ab..51a66c40b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -19,29 +19,31 @@ classifiers = [ "Programming Language :: Python", ] dependencies = [ - "asdf", - "astropy", - "astroquery", - "bokeh>=3", - "crds", - "cryptography", - "django", - "inflection", - "jinja2", - "jsonschema", - "jwst", - "jwst_reffiles", - "matplotlib", - "numpy", - "numpydoc", - "pandas", - "psycopg2-binary", - "pysiaf", - "pyvo", - "scipy", - "sqlalchemy", - "stdatamodels", - "wtforms", + "asdf>=3.1.0,<4", + "astropy>=6.0,<7", + "astroquery>=0.4.7,<0.5.0", + "beautifulsoup4>=4.12.3,<5", + "bokeh>=3.4.0,<4", + "celery>=5.3.6,<6", + "crds>=11.17.19,<12", + "django>=5.0.3,<6", + "gunicorn>=22.0.0,<23.0.0", + "inflection>=0.5.1,<0.6", + "jsonschema>=4.21.1,<5", + "jwst>=1.13.4,<2", + "jwst_backgrounds>=1.2.0,<1.3.0", + "jwst_reffiles>=1.0.1", + "matplotlib>=3.8.3,<4", + "numpy>=1.26.4,<2", + "pandas>=2.2.1,<3", + "psycopg2-binary>=2.9.9,<3", + "pysiaf>=0.22.0", + "pyvo>=1.5.1,<2", + "redis>=5.0.3,<6", + "scipy>=1.12.0,<2", + "selenium>=4.18.1,<5", + "sqlalchemy>=2.0.29,<3", + "wtforms>=3.1.2,<4", ] dynamic = [ "version", @@ -55,9 +57,11 @@ test = [ "pytest-mock", ] docs = [ + "numpydoc", "sphinx", "sphinx_rtd_theme", "stsci_rtd_theme", + "sphinx_automodapi", ] [project.license] diff --git a/requirements.txt b/requirements.txt deleted file mode 100644 index 0edf7d9ea..000000000 --- a/requirements.txt +++ /dev/null @@ -1,41 +0,0 @@ -astropy==5.3.3 -astroquery==0.4.6 -bandit==1.7.5 -beautifulsoup4==4.12.2 -bokeh==3.3.0 -celery==5.3.4 -cryptography==41.0.7 -django==4.2.5 -inflection==0.5.1 -ipython==8.16.1 -jinja2==3.1.2 -jsonschema==4.19.1 -jwst==1.12.3 -jwst_backgrounds==1.2.0 -matplotlib==3.8.0 -nodejs==20.8.0 -numpy==1.25.2 -numpydoc==1.5.0 -pandas==2.1.1 -psycopg2-binary==2.9.7 -pysiaf==0.20.0 -pysqlite3==0.5.2 -pytest==7.4.2 -pytest-cov==4.1.0 -pytest-mock==3.11.1 -pyvo==1.4.2 -pyyaml==6.0.1 -redis==5.0.0 -ruff==0.1.6 -scipy==1.11.4 -selenium==4.13.0 -setuptools==68.2.2 -sphinx==7.2.6 -sphinx_rtd_theme==1.3.0 -sqlalchemy==2.0.23 -stdatamodels==1.8.3 -stsci_rtd_theme==1.0.0 -twine==4.0.2 -vine==5.1.0 -wtforms==3.0.1 -git+https://github.com/spacetelescope/jwst_reffiles#egg=jwst_reffiles diff --git a/rtd_requirements.txt b/rtd_requirements.txt deleted file mode 100644 index abac6b128..000000000 --- a/rtd_requirements.txt +++ /dev/null @@ -1,15 +0,0 @@ -sphinx_automodapi>=0.15.0 -bokeh==2.4.3 -celery==5.3.4 -cython>=3.0.0 -django==4.2.5 -docutils>=0.18.1 -jwst==1.12.3 -pygments==2.16.1 -pytest==7.4.2 -redis==5.0.0 -selenium==4.13.0 -sphinx==7.2.6 -stsci_rtd_theme==1.0.0 -tomli==2.0.1 -git+https://github.com/spacetelescope/jwst_reffiles diff --git a/style_guide/example.py b/style_guide/example.py index 47db3b3a0..d145529de 100644 --- a/style_guide/example.py +++ b/style_guide/example.py @@ -73,7 +73,7 @@ # Global variables should be avoided, but if used should be named with # all-caps -A_GLOBAL_VARIABLE = 'foo' # type: str +A_GLOBAL_VARIABLE = "foo" # type: str @log_fail @@ -92,14 +92,14 @@ def my_main_function(path: str, filter: str) -> None: The filter to process (e.g. "F606W"). """ - logging.info('Using {} as an input file'.format(path)) + logging.info("Using {} as an input file".format(path)) an_int = 1 # type: int a_float = 3.14 # type: float a_bool = True # type: bool - a_list = ['Dog', 'Cat', 'Turtle', False, 7] # type: List[Union[str, bool, int]] - a_tuple = ('Dog', 'Cat', 'Turtle', False, 7) # type: Tuple[str, str, str, bool, int] - a_dict = {'key1': 'value1', 'key2': 'value2'} # type: Dict[str, str] + a_list = ["Dog", "Cat", "Turtle", False, 7] # type: List[Union[str, bool, int]] + a_tuple = ("Dog", "Cat", "Turtle", False, 7) # type: Tuple[str, str, str, bool, int] + a_dict = {"key1": "value1", "key2": "value2"} # type: Dict[str, str] an_obj = object() # type: object result = some_other_function(an_int, a_float, a_bool, a_list, a_tuple, a_dict, an_obj) # type: Optional[int] @@ -117,21 +117,13 @@ def parse_args() -> argparse.Namespace: """ # Create help strings - path_help = 'The path to the input file.' # type: str + path_help = "The path to the input file." # type: str filter_help = 'The filter to process (e.g. "F606W").' # type: str # Add arguments parser = argparse.ArgumentParser() # type: argparse.ArgumentParser - parser.add_argument('path', - type=str, - default=os.getcwd(), - help=path_help) - parser.add_argument('-f --filter', - dest='filter', - type=str, - required=False, - default='F606W', - help=filter_help) + parser.add_argument("path", type=str, default=os.getcwd(), help=path_help) + parser.add_argument("-f --filter", dest="filter", type=str, required=False, default="F606W", help=filter_help) # Parse args args = parser.parse_args() # type: argparse.Namespace @@ -140,8 +132,7 @@ def parse_args() -> argparse.Namespace: @log_timing -def some_other_function(an_int: int, a_float: float, a_bool: bool, a_list: List[Any], - a_tuple: Tuple[Any], a_dict: Dict[Any, Any], an_obj: object) -> int: +def some_other_function(an_int: int, a_float: float, a_bool: bool, a_list: List[Any], a_tuple: Tuple[Any], a_dict: Dict[Any, Any], an_obj: object) -> int: """This function just does a bunch of nonsense. But it serves as a decent example of some things. @@ -170,8 +161,8 @@ def some_other_function(an_int: int, a_float: float, a_bool: bool, a_list: List[ """ # File I/O should be handeled with 'with open' when possible - with open('my_file', 'w') as f: - f.write('My favorite integer is {}'.format(an_int)) + with open("my_file", "w") as f: + f.write("My favorite integer is {}".format(an_int)) # Operators should be separated by spaces logging.info(a_float + a_float) @@ -179,10 +170,9 @@ def some_other_function(an_int: int, a_float: float, a_bool: bool, a_list: List[ return an_int -if __name__ == '__main__': - +if __name__ == "__main__": # Configure logging - module = os.path.basename(__file__).strip('.py') + module = os.path.basename(__file__).strip(".py") configure_logging(module) args = parse_args() # type: argparse.Namespace diff --git a/style_guide/typing_demo/typing_demo_1.py b/style_guide/typing_demo/typing_demo_1.py index 33c11e397..ad4bc30d0 100644 --- a/style_guide/typing_demo/typing_demo_1.py +++ b/style_guide/typing_demo/typing_demo_1.py @@ -7,8 +7,7 @@ """ import sys -from typing import (List, Set, Dict, Tuple, Union, Optional, Callable, - Iterable, Any) +from typing import Any, Callable, Dict, Iterable, List, Optional, Set, Tuple, Union assert sys.version_info >= (3, 6) # PEP 526 added variable annotations @@ -18,7 +17,7 @@ a_string: str = "jwql" a_list: List[int] = [1] a_set: Set[int] = {1, 2, 3} -a_dict: Dict[str, bool] = {'jwql': True} # Have to specify both keys and values +a_dict: Dict[str, bool] = {"jwql": True} # Have to specify both keys and values # For python versions prior to 3.6, the variable annotation syntax uses comments: # annotated_variable = 1 # type: int @@ -68,6 +67,7 @@ def a_generator() -> Iterable[int]: # Type annotations are stored in __annotations__, either as a local variable # or as an object attribute. + def print_annotations(arg: Any) -> bool: if not hasattr(arg, "__annotations__"): print("Sorry, that argument doesn't have its own __annotations__.") @@ -76,8 +76,7 @@ def print_annotations(arg: Any) -> bool: return bool(arg.__annotations__) -for name in ["an_integer", "a_generic_function", "two_arg_function", - "func_alias", "anon_func", "a_generator"]: +for name in ["an_integer", "a_generic_function", "two_arg_function", "func_alias", "anon_func", "a_generator"]: var = locals()[name] print(f"Annotations for {name}:") if not print_annotations(var):