Skip to content
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

Issue 65 #100

Merged
merged 25 commits into from
Dec 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
1d15813
Ruff auto-fixes for linting issues
eigenbeam Nov 27, 2024
34b5d9f
Resolve remainder of Ruff checks
eigenbeam Nov 27, 2024
184d350
Applies ruff (black) code formatting rules
eigenbeam Nov 27, 2024
d8508ff
Applies ruff (black) code formatting rules
eigenbeam Nov 27, 2024
ffcc452
Applies ruff (black) code formatting rules
eigenbeam Nov 27, 2024
2c75b3c
Applies ruff (black) code formatting rules
eigenbeam Nov 27, 2024
dbff7f6
Applies ruff (black) code formatting rules
eigenbeam Nov 27, 2024
3921cac
Applies ruff (black) code formatting rules
eigenbeam Nov 27, 2024
683247a
Applies ruff (black) code formatting rules
eigenbeam Nov 27, 2024
0a87b0f
Applies ruff (black) code formatting rules
eigenbeam Nov 27, 2024
1a85cc1
Applies ruff (black) code formatting rules
eigenbeam Nov 27, 2024
7a0afb4
Applies ruff (black) code formatting rules
eigenbeam Nov 27, 2024
8b7091d
Applies ruff (black) code formatting rules
eigenbeam Nov 27, 2024
77fabf0
Let ruff cleanup & sort imports
eigenbeam Nov 27, 2024
c51cb58
Adds & configures ruff tool
eigenbeam Nov 27, 2024
e8a9a9e
Add ruff checks to the build-test GHA workflow
eigenbeam Nov 27, 2024
893dc1f
Update README with ruff instructions
eigenbeam Dec 3, 2024
e15471d
Add isort rule to ruff linter
eigenbeam Dec 3, 2024
71d0a6c
Fixes line-length issues
eigenbeam Dec 3, 2024
2c4ddc8
Fixes line-length issues
eigenbeam Dec 3, 2024
c94b813
Fixes line-length issues
eigenbeam Dec 3, 2024
fbfbdb6
Fixes line-length issues
eigenbeam Dec 3, 2024
f2bc0e0
Fix GHA configuration for ruff
eigenbeam Dec 3, 2024
06d36a8
Fix merge issue
eigenbeam Dec 3, 2024
ce6eb99
Resolve errors from the rebase on main
eigenbeam Dec 3, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion .github/workflows/build-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,16 @@ jobs:

- run: poetry install --no-interaction

- run: poetry run pytest
- name: Check formatting
uses: astral-sh/ruff-action@v1
with:
args: "format --check"
src: "./src"

- name: Lint code
uses: astral-sh/ruff-action@v1
with:
src: "./src"

- name: Test
run: poetry run pytest
31 changes: 31 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,37 @@ installed, you should be able to run:

$ poetry run ptw . --now --clear

### Running the linter for code style issues:

$ poetry run ruff check

[The `ruff` tool](https://docs.astral.sh/ruff/linter/) will check
the source code for conformity with various style rules. Some of
these can be fixed by `ruff` itself, and if so, the output will
describe how to automatically fix these issues.

The CI/CD pipeline will run these checks whenever new commits are
pushed to GitHub, and the results will be available in the GitHub
Actions output.

### Running the code formatter

$ poetry run ruff format

[The `ruff` tool](https://docs.astral.sh/ruff/formatter/) will check
the source code for conformity with source code formatting rules. It
will also fix any issues it finds and leave the changes uncommitted
so you can review the changes prior to adding them to the codebase.

As with the linter, the CI/CD pipeline will run the formatter when
commits are pushed to GitHub.

### Ruff integration with your editor

Rather than running `ruff` manually from the commandline, it can be
integrated with the editor of your choice. See the
[ruff editor integration](https://docs.astral.sh/ruff/editors/) guide.

### Releasing

* Update the CHANGELOG to include details of the changes included in the new
Expand Down
3 changes: 3 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,9 @@ replace = 'v{new_version}'
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"

[tool.ruff.lint]
select = ["E", "F", "I"]

[tool.mypy]
files = ["src", "tests"]

Expand Down
17 changes: 9 additions & 8 deletions src/nsidc/metgen/aws.py
Original file line number Diff line number Diff line change
@@ -1,32 +1,32 @@
import boto3


KINESIS_PARTITION_KEY = "metgenc-duck"


def kinesis_stream_exists(stream_name):
"""
Predicate which determines if a Kinesis stream with the given name exists
in the configured AWS environment.
"""
client = boto3.client("kinesis")
try:
summary = client.describe_stream_summary(StreamName=stream_name)
client.describe_stream_summary(StreamName=stream_name)
return True
except Exception as e:
except Exception:
return False


def post_to_kinesis(stream_name, cnm_message):
"""
Posts a message to a Kinesis stream.
"""
client = boto3.client("kinesis")
result = client.put_record(
StreamName=stream_name,
Data=cnm_message,
PartitionKey=KINESIS_PARTITION_KEY
StreamName=stream_name, Data=cnm_message, PartitionKey=KINESIS_PARTITION_KEY
)

return result['ShardId']
return result["ShardId"]


def staging_bucket_exists(bucket_name):
"""
Expand All @@ -37,9 +37,10 @@ def staging_bucket_exists(bucket_name):
try:
client.head_bucket(Bucket=bucket_name)
return True
except Exception as e:
except Exception:
return False


def stage_file(s3_bucket_name, object_name, *, data=None, file=None):
"""
Stages data into an s3 bucket at a given path.
Expand Down
123 changes: 92 additions & 31 deletions src/nsidc/metgen/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,10 @@

import click

from nsidc.metgen import config
from nsidc.metgen import metgen
from nsidc.metgen import constants
from nsidc.metgen import config, constants, metgen

LOGGER = logging.getLogger("metgenc")

LOGGER = logging.getLogger('metgenc')

@click.group(epilog="For detailed help on each command, run: metgenc COMMAND --help")
def cli():
Expand All @@ -16,72 +14,135 @@ def cli():
Cumulus, and post CNM messages."""
pass


@cli.command()
@click.option('-c', '--config', help='Path to configuration file to create or replace')
@click.option("-c", "--config", help="Path to configuration file to create or replace")
def init(config):
"""Populates a configuration file based on user input."""
click.echo(metgen.banner())
config = metgen.init_config(config)
click.echo(f'Initialized the metgen configuration file {config}')
click.echo(f"Initialized the metgen configuration file {config}")


@cli.command()
@click.option('-c', '--config', 'config_filename', help='Path to configuration file to display', required=True)
@click.option(
"-c",
"--config",
"config_filename",
help="Path to configuration file to display",
required=True,
)
def info(config_filename):
"""Summarizes the contents of a configuration file."""
click.echo(metgen.banner())
configuration = config.configuration(config.config_parser_factory(config_filename), {})
configuration = config.configuration(
config.config_parser_factory(config_filename), {}
)
metgen.init_logging(configuration)
configuration.show()


@cli.command()
@click.option('-c', '--config', 'config_filename', help='Path to configuration file', required=True)
@click.option('-t', '--type', 'content_type', help='JSON content type', default='cnm', show_default=True)
@click.option(
"-c",
"--config",
"config_filename",
help="Path to configuration file",
required=True,
)
@click.option(
"-t",
"--type",
"content_type",
help="JSON content type",
default="cnm",
show_default=True,
)
def validate(config_filename, content_type):
"""Validates the contents of local JSON files."""
click.echo(metgen.banner())
configuration = config.configuration(config.config_parser_factory(config_filename), {})
configuration = config.configuration(
config.config_parser_factory(config_filename), {}
)
metgen.init_logging(configuration)
metgen.validate(configuration, content_type)


@cli.command()
@click.option('-c', '--config', 'config_filename', required=True,
help='Path to configuration file')
@click.option('-d', '--dry-run', is_flag=True, required=False, default=None,
help='Don\'t stage files on S3 or publish messages to Kinesis')
@click.option('-e', '--env', help='environment',
default=constants.DEFAULT_CUMULUS_ENVIRONMENT, show_default=True)
@click.option('-n', '--number', metavar='count', required=False,
default=constants.DEFAULT_NUMBER, help="Process at most 'count' granules.")
@click.option('-wc', '--write-cnm', is_flag=True, required=False, default=None,
help="Write CNM messages to files.")
@click.option('-o', '--overwrite', is_flag=True, required=False, default=None,
help="Overwrite existing UMM-G files.")
@click.option(
"-c",
"--config",
"config_filename",
help="Path to configuration file",
required=True,
)
@click.option(
"-d",
"--dry-run",
is_flag=True,
required=False,
default=None,
help="Don't stage files on S3 or publish messages to Kinesis",
)
@click.option(
"-e",
"--env",
help="environment",
default=constants.DEFAULT_CUMULUS_ENVIRONMENT,
show_default=True,
)
@click.option(
"-n",
"--number",
help="Process at most 'count' granules.",
metavar="count",
required=False,
default=constants.DEFAULT_NUMBER,
)
@click.option(
"-wc",
"--write-cnm",
is_flag=True,
required=False,
default=None,
help="Write CNM messages to files.",
)
@click.option(
"-o",
"--overwrite",
is_flag=True,
required=False,
default=None,
help="Overwrite existing UMM-G files.",
)
def process(config_filename, dry_run, env, number, write_cnm, overwrite):
"""Processes science data files based on configuration file contents."""
click.echo(metgen.banner())
overrides = {
'dry_run': dry_run,
'number': number,
'overwrite_ummg': overwrite,
'write_cnm_file': write_cnm,
"dry_run": dry_run,
"number": number,
"overwrite_ummg": overwrite,
"write_cnm_file": write_cnm,
}
try:
configuration = config.configuration(config.config_parser_factory(config_filename), overrides, env)
configuration = config.configuration(
config.config_parser_factory(config_filename), overrides, env
)
metgen.init_logging(configuration)
configuration.show()
config.validate(configuration)
metgen.process(configuration)
except config.ValidationError as e:
logger = logging.getLogger('metgenc')
logger = logging.getLogger("metgenc")
logger.error("\nThe configuration is invalid:")
for error in e.errors:
logger.error(f" * {error}")
exit(1)
except Exception as e:
logger = logging.getLogger('metgenc')
logger = logging.getLogger("metgenc")
logger.error("\nUnable to process data: " + str(e))
exit(1)
click.echo(f'Processing complete')
click.echo("Processing complete")


if __name__ == "__main__":
Expand Down
Loading
Loading