From 333890d312f66354748fd8ff32bd7cdb3dd966a7 Mon Sep 17 00:00:00 2001 From: Jaden Abrams <96440993+jadenabrams100@users.noreply.github.com> Date: Fri, 19 Apr 2024 12:48:54 -0400 Subject: [PATCH 01/27] docs: add coverity badge to README.md (#3630) Add Coverity badge to README.md. This would make it easier for the average contributor (and the public as well) to see that GRASS is using the Coverity platform for static analysis. --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 49a84e661a4..ce6a2ead887 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,7 @@ [![OSGeo4W](https://github.com/OSGeo/grass/workflows/OSGeo4W/badge.svg)](https://github.com/OSGeo/grass/actions?query=workflow%3AOSGeo4W) [![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/OSGeo/grass/badge)](https://securityscorecards.dev/viewer/?uri=github.com/OSGeo/grass) [![OpenSSF Best Practices](https://www.bestpractices.dev/projects/2470/badge)](https://www.bestpractices.dev/projects/2470) +[![Coverity](https://scan.coverity.com/projects/1038/badge.svg)](https://scan.coverity.com/projects/grass) [![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.5176030.svg)](https://doi.org/10.5281/zenodo.5176030) [![Join the chat at https://gitter.im/grassgis/community](https://badges.gitter.im/grassgis/community.svg)](https://gitter.im/grassgis/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) From 6498c7e3000fc5997e460f4dfa87578845192d20 Mon Sep 17 00:00:00 2001 From: Tomas Zigo <50632337+tmszi@users.noreply.github.com> Date: Sat, 20 Apr 2024 08:34:12 +0200 Subject: [PATCH 02/27] v.db.dropcolumn: fix enclosing column name with SQL standard double quotes (#3632) --- scripts/v.db.dropcolumn/v.db.dropcolumn.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/scripts/v.db.dropcolumn/v.db.dropcolumn.py b/scripts/v.db.dropcolumn/v.db.dropcolumn.py index 937f573006c..b408c83395a 100755 --- a/scripts/v.db.dropcolumn/v.db.dropcolumn.py +++ b/scripts/v.db.dropcolumn/v.db.dropcolumn.py @@ -96,11 +96,11 @@ def main(): # see db_sqltype_name() for type names if f[1] == "CHARACTER": # preserve field length for sql type "CHARACTER" - coltypes.append("%s %s(%s)" % (f[0], f[1], f[2])) + coltypes.append(f'"{f[0]}" {f[1]}({f[2]})') else: - coltypes.append("%s %s" % (f[0], f[1])) + coltypes.append(f'"{f[0]}" {f[1]}') - colnames = ", ".join(colnames) + colnames = ", ".join([f'"{col}"' for col in colnames]) coltypes = ", ".join(coltypes) cmds = [ @@ -119,7 +119,7 @@ def main(): table=table, coldef=coltypes, colnames=colnames, keycol=keycol ) else: - sql = "ALTER TABLE %s DROP COLUMN %s" % (table, column) + sql = f'ALTER TABLE {table} DROP COLUMN "{column}"' try: grass.write_command( From 307bfcdb9d6a0e495c956322c4c5d3da97d9fe64 Mon Sep 17 00:00:00 2001 From: Tomas Zigo <50632337+tmszi@users.noreply.github.com> Date: Sat, 20 Apr 2024 16:54:29 +0200 Subject: [PATCH 03/27] v.db.renamecolumn: fix enclosing column name with SQL standard double quotes (#3631) --- scripts/v.db.renamecolumn/v.db.renamecolumn.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/scripts/v.db.renamecolumn/v.db.renamecolumn.py b/scripts/v.db.renamecolumn/v.db.renamecolumn.py index 0309cff406a..87f1850a57c 100755 --- a/scripts/v.db.renamecolumn/v.db.renamecolumn.py +++ b/scripts/v.db.renamecolumn/v.db.renamecolumn.py @@ -103,12 +103,12 @@ def main(): # some tricks if driver in ["sqlite", "dbf"]: if oldcoltype.upper() == "CHARACTER": - colspec = "%s varchar(%s)" % (newcol, oldcollength) + colspec = f"{newcol} varchar({oldcollength})" else: - colspec = "%s %s" % (newcol, oldcoltype) + colspec = f"{newcol} {oldcoltype}" grass.run_command("v.db.addcolumn", map=map, layer=layer, column=colspec) - sql = "UPDATE %s SET %s=%s" % (table, newcol, oldcol) + sql = f'UPDATE {table} SET "{newcol}"="{oldcol}"' grass.write_command( "db.execute", input="-", database=database, driver=driver, stdin=sql ) @@ -119,12 +119,12 @@ def main(): else: newcoltype = oldcoltype - sql = "ALTER TABLE %s CHANGE %s %s %s" % (table, oldcol, newcol, newcoltype) + sql = f'ALTER TABLE {table} CHANGE "{oldcol}" "{newcol}" {newcoltype}' grass.write_command( "db.execute", input="-", database=database, driver=driver, stdin=sql ) else: - sql = "ALTER TABLE %s RENAME %s TO %s" % (table, oldcol, newcol) + sql = f'ALTER TABLE {table} RENAME "{oldcol}" TO "{newcol}"' grass.write_command( "db.execute", input="-", database=database, driver=driver, stdin=sql ) From ef730b99931719ee3f1bdc76aedba771fa15458d Mon Sep 17 00:00:00 2001 From: Tomas Zigo <50632337+tmszi@users.noreply.github.com> Date: Sat, 20 Apr 2024 18:04:12 +0200 Subject: [PATCH 04/27] v.db.addcolumn: fix enclosing column name with SQL standard double quotes (#3633) * Fix fatal message * Fix maximum number of string split by whitespace string * Fix add new column name type --- python/grass/script/testsuite/test_names.py | 6 +++++- scripts/v.db.addcolumn/v.db.addcolumn.py | 15 +++++++++++++-- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/python/grass/script/testsuite/test_names.py b/python/grass/script/testsuite/test_names.py index 72db4aff174..6d48596c392 100644 --- a/python/grass/script/testsuite/test_names.py +++ b/python/grass/script/testsuite/test_names.py @@ -109,7 +109,11 @@ def works_for_vector_table_column(self, name): try: gs.run_command("v.edit", map=name, tool="create") gs.run_command("v.db.addtable", map=name) - gs.run_command("v.db.addcolumn", map=name, columns=name) + gs.run_command( + "v.db.addcolumn", + map=name, + columns=f"{name} integer", + ) works = True except gs.CalledModuleError: works = False diff --git a/scripts/v.db.addcolumn/v.db.addcolumn.py b/scripts/v.db.addcolumn/v.db.addcolumn.py index 2ce1a3eedc2..8d8e322118c 100755 --- a/scripts/v.db.addcolumn/v.db.addcolumn.py +++ b/scripts/v.db.addcolumn/v.db.addcolumn.py @@ -42,6 +42,8 @@ import atexit import os +import re + from grass.exceptions import CalledModuleError import grass.script as grass @@ -98,17 +100,26 @@ def main(): column_existing = grass.vector_columns(map, int(layer)).keys() add_str = "BEGIN TRANSACTION\n" + pattern = re.compile(r"\s+") for col in columns: if not col: grass.fatal(_("There is an empty column. Did you leave a trailing comma?")) - col_name = col.split(" ")[0].strip() + whitespace = re.search(pattern, col) + if not whitespace: + grass.fatal( + _( + "Incorrect new column(s) format, use" + " <'name type [,name type, ...]'> format, please." + ) + ) + col_name, col_type = col.split(whitespace.group(0), 1) if col_name in column_existing: grass.error( _("Column <{}> is already in the table. Skipping.").format(col_name) ) continue grass.verbose(_("Adding column <{}> to the table").format(col_name)) - add_str += f"ALTER TABLE {table} ADD COLUMN {col};\n" + add_str += f'ALTER TABLE {table} ADD COLUMN "{col_name}" {col_type};\n' add_str += "END TRANSACTION" sql_file = grass.tempfile() rm_files.append(sql_file) From 5f6977e40cd182d56aa0b6e792667408f122249a Mon Sep 17 00:00:00 2001 From: Tomas Zigo <50632337+tmszi@users.noreply.github.com> Date: Sat, 20 Apr 2024 21:29:14 +0200 Subject: [PATCH 05/27] db/drivers/odbc: set ODBC MySQL DB backend SQL ANSI_QUOTES MODE (#3635) Which allow to use SQL standard double quotes instead of backticks for escaping column name. --- db/drivers/odbc/db.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/db/drivers/odbc/db.c b/db/drivers/odbc/db.c index 6da5ebdd336..d27375a5ddc 100644 --- a/db/drivers/odbc/db.c +++ b/db/drivers/odbc/db.c @@ -13,6 +13,7 @@ int db__driver_open_database(dbHandle *handle) SQLRETURN ret; SQLINTEGER err; dbConnection connection; + SQLCHAR dbms_name[256]; /* Open connection */ if (open_connection() != DB_OK) @@ -39,6 +40,30 @@ int db__driver_open_database(dbHandle *handle) return DB_FAILED; } + /* Find ODBC DB driver */ + SQLGetInfo(ODconn, SQL_DBMS_NAME, (SQLPOINTER)dbms_name, sizeof(dbms_name), + NULL); + + if (strcmp((CHAR *)dbms_name, "MySQL") == 0 || + strcmp((CHAR *)dbms_name, "MariaDB") == 0) { + cursor *c; + + c = alloc_cursor(); + if (c == NULL) + return DB_FAILED; + + /* Set SQL ANSI_QUOTES MODE which allow to use double quotes instead of + * backticks */ + SQLExecDirect(c->stmt, (SQLCHAR *)"SET SQL_MODE=ANSI_QUOTES", SQL_NTS); + + G_debug( + 3, + "db__driver_open_database(): Set ODBC %s DB SQL ANSI_QUOTES MODE", + dbms_name); + + free_cursor(c); + } + return DB_OK; } From e6530c3cc54f80f74e402a776c8d0055a739e158 Mon Sep 17 00:00:00 2001 From: Tomas Zigo <50632337+tmszi@users.noreply.github.com> Date: Sun, 21 Apr 2024 18:41:22 +0200 Subject: [PATCH 06/27] db/drivers/odbc: catch and handle return value from setting MySQL SQL ANSI mode (#3637) * db/drivers/odbc: catch and handle return value from setting MySQL SQL ANSI mode * Free DB SQL string * Free cursor and disconnect from DB --- db/drivers/odbc/db.c | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/db/drivers/odbc/db.c b/db/drivers/odbc/db.c index d27375a5ddc..e67fa147633 100644 --- a/db/drivers/odbc/db.c +++ b/db/drivers/odbc/db.c @@ -46,22 +46,39 @@ int db__driver_open_database(dbHandle *handle) if (strcmp((CHAR *)dbms_name, "MySQL") == 0 || strcmp((CHAR *)dbms_name, "MariaDB") == 0) { + dbString sql; cursor *c; c = alloc_cursor(); if (c == NULL) return DB_FAILED; + db_init_string(&sql); + db_set_string(&sql, "SET SQL_MODE=ANSI_QUOTES;"); + /* Set SQL ANSI_QUOTES MODE which allow to use double quotes instead of * backticks */ - SQLExecDirect(c->stmt, (SQLCHAR *)"SET SQL_MODE=ANSI_QUOTES", SQL_NTS); + ret = SQLExecDirect(c->stmt, (SQLCHAR *)db_get_string(&sql), SQL_NTS); + + if ((ret != SQL_SUCCESS) && (ret != SQL_SUCCESS_WITH_INFO)) { + SQLGetDiagRec(SQL_HANDLE_STMT, c->stmt, 1, NULL, &err, msg, + sizeof(msg), NULL); + db_d_append_error("SQLExecDirect():\n%s\n%s (%d)\n", + db_get_string(&sql), msg, (int)err); + db_d_report_error(); + free_cursor(c); + db_free_string(&sql); + SQLDisconnect(ODconn); + close_connection(); + + return DB_FAILED; + } - G_debug( - 3, - "db__driver_open_database(): Set ODBC %s DB SQL ANSI_QUOTES MODE", - dbms_name); + G_debug(3, "db__driver_open_database(): Set ODBC %s DB %s", dbms_name, + db_get_string(&sql)); free_cursor(c); + db_free_string(&sql); } return DB_OK; From 7413740dd81c11c2909ad10e7c3161fc097088f9 Mon Sep 17 00:00:00 2001 From: Tomas Zigo <50632337+tmszi@users.noreply.github.com> Date: Mon, 22 Apr 2024 04:58:47 +0200 Subject: [PATCH 07/27] db/drivers/mysql: print debug info for setting MySQL ANSI SQL mode (#3638) * Free DB SQL string * Release DB connection --- db/drivers/mysql/db.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/db/drivers/mysql/db.c b/db/drivers/mysql/db.c index 7e2a8146310..5c98c652e95 100644 --- a/db/drivers/mysql/db.c +++ b/db/drivers/mysql/db.c @@ -23,6 +23,7 @@ int db__driver_open_database(dbHandle *handle) const char *name; dbConnection default_connection; MYSQL *res; + dbString sql; db_get_connection(&default_connection); name = db_get_handle_dbname(handle); @@ -63,14 +64,25 @@ int db__driver_open_database(dbHandle *handle) db_d_report_error(); return DB_FAILED; } + + db_init_string(&sql); + db_set_string(&sql, "SET SQL_MODE=ANSI_QUOTES;"); + /* Set SQL ANSI_QUOTES MODE which allow to use double quotes instead of * backticks */ - if (mysql_query(connection, "SET SQL_MODE=ANSI_QUOTES") != 0) { + if (mysql_query(connection, db_get_string(&sql)) != 0) { db_d_append_error("%s %s", _("Unable to set SQL ANSI_QUOTES mode:"), mysql_error(connection)); db_d_report_error(); + db_free_string(&sql); + mysql_close(connection); + return DB_FAILED; } + G_debug(3, "db__driver_open_database(): Set ODBC MySQL DB %s", + db_get_string(&sql)); + + db_free_string(&sql); } return DB_OK; From b55c77944f2a06aec9190c5dde5aa93cc88dbb18 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 22 Apr 2024 19:45:31 +0000 Subject: [PATCH 08/27] CI(deps): Update actions/checkout action to v4.1.3 (#3640) --- .github/workflows/clang-format-check.yml | 2 +- .github/workflows/coverity.yml | 2 +- .github/workflows/periodic_update.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/clang-format-check.yml b/.github/workflows/clang-format-check.yml index 6f1586f4b7c..0cf81068b2b 100644 --- a/.github/workflows/clang-format-check.yml +++ b/.github/workflows/clang-format-check.yml @@ -16,7 +16,7 @@ jobs: name: Formatting Check runs-on: ubuntu-latest steps: - - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + - uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3 with: persist-credentials: false - uses: DoozyX/clang-format-lint-action@11b773b1598aa4ae3b32f023701bca5201c3817d # v0.17 diff --git a/.github/workflows/coverity.yml b/.github/workflows/coverity.yml index 8d56eb1d8df..d8bdfefbb33 100644 --- a/.github/workflows/coverity.yml +++ b/.github/workflows/coverity.yml @@ -17,7 +17,7 @@ jobs: runs-on: ubuntu-22.04 if: github.repository == 'OSGeo/grass' steps: - - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + - uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3 - name: Get dependencies run: | diff --git a/.github/workflows/periodic_update.yml b/.github/workflows/periodic_update.yml index 75c50089ed9..4b8cd94580b 100644 --- a/.github/workflows/periodic_update.yml +++ b/.github/workflows/periodic_update.yml @@ -21,7 +21,7 @@ jobs: - name: Create URL to the run output id: vars run: echo "run-url=https://github.com/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID" >> $GITHUB_OUTPUT - - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + - uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3 - name: "Check that autoconf scripts are up-to-date:" run: | rm -f config.guess config.sub From 9c86360d3f44ebe2e4e4483d23be7c2cb583b6ce Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 22 Apr 2024 20:41:29 +0000 Subject: [PATCH 09/27] CI(deps): Update super-linter/super-linter action to v6.4.1 (#3642) --- .github/workflows/super-linter.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/super-linter.yml b/.github/workflows/super-linter.yml index c768fc80175..6712d5d9323 100644 --- a/.github/workflows/super-linter.yml +++ b/.github/workflows/super-linter.yml @@ -34,7 +34,7 @@ jobs: # list of files that changed across commits fetch-depth: 0 - name: Lint code base - uses: super-linter/super-linter/slim@9d8128f17796a16326ceed5a607d5639a47feb82 # v6.4.0 + uses: super-linter/super-linter/slim@4758be622215d0954c8353ee4877ffd60111cf8e # v6.4.1 env: DEFAULT_BRANCH: main # To report GitHub Actions status checks From 96aa1b4ed715c256083756a5336d5299e889f1b7 Mon Sep 17 00:00:00 2001 From: Huidae Cho Date: Mon, 22 Apr 2024 15:33:55 -0700 Subject: [PATCH 10/27] Define (read|write)_png only #ifdef HAVE_PNG_H (#3647) --- lib/pngdriver/pngdriver.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/pngdriver/pngdriver.h b/lib/pngdriver/pngdriver.h index 62b61aa700e..0a4b9564e72 100644 --- a/lib/pngdriver/pngdriver.h +++ b/lib/pngdriver/pngdriver.h @@ -54,13 +54,17 @@ extern void read_image(void); extern void read_ppm(void); extern void read_pgm(void); extern void read_bmp(void); +#ifdef HAVE_PNG_H extern void read_png(void); +#endif extern void write_image(void); extern void write_ppm(void); extern void write_pgm(void); extern void write_bmp(void); +#ifdef HAVE_PNG_H extern void write_png(void); +#endif extern void png_init_color_table(void); extern unsigned int png_get_color(int, int, int, int); From b0eaced767d007b6dd9c4e0b72efa77f131b2b29 Mon Sep 17 00:00:00 2001 From: Huidae Cho Date: Mon, 22 Apr 2024 15:39:12 -0700 Subject: [PATCH 11/27] gmath: Include only one header for FFTW (#3641) * gmath: Include only one header for FFTW * Prefer FFTW3 > DFFTW > FFTW * Use elif defined instead of C2x elifdef; Reorder to FFTW3, FFTW, DFFTW --- lib/gmath/fft.c | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/lib/gmath/fft.c b/lib/gmath/fft.c index c0dea7b7d0e..3615fb602b2 100644 --- a/lib/gmath/fft.c +++ b/lib/gmath/fft.c @@ -25,20 +25,16 @@ #include -#if defined(HAVE_FFTW_H) || defined(HAVE_DFFTW_H) || defined(HAVE_FFTW3_H) +#if defined(HAVE_FFTW3_H) || defined(HAVE_FFTW_H) || defined(HAVE_DFFTW_H) -#ifdef HAVE_FFTW_H -#include -#endif - -#ifdef HAVE_DFFTW_H -#include -#endif - -#ifdef HAVE_FFTW3_H +#if defined(HAVE_FFTW3_H) #include #define c_re(c) ((c)[0]) #define c_im(c) ((c)[1]) +#elif defined(HAVE_FFTW_H) +#include +#elif defined(HAVE_DFFTW_H) +#include #endif #include From adfeb16f833d9b1283c0f8aef9a9de93421861fb Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 22 Apr 2024 19:14:19 -0400 Subject: [PATCH 12/27] CI(deps): Update actions/upload-artifact action to v4.3.3 (#3646) --- .github/actions/create-upload-suggestions/action.yml | 4 ++-- .github/workflows/macos.yml | 2 +- .github/workflows/python-code-quality.yml | 4 ++-- .github/workflows/ubuntu.yml | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/actions/create-upload-suggestions/action.yml b/.github/actions/create-upload-suggestions/action.yml index 858263d8588..16f7ed4c337 100644 --- a/.github/actions/create-upload-suggestions/action.yml +++ b/.github/actions/create-upload-suggestions/action.yml @@ -176,7 +176,7 @@ runs: echo "diff-file-name=${INPUT_DIFF_FILE_NAME}" >> "${GITHUB_OUTPUT}" env: INPUT_DIFF_FILE_NAME: ${{ steps.tool-name-safe.outputs.diff-file-name }} - - uses: actions/upload-artifact@1746f4ab65b179e0ea60a494b83293b640dd5bba # v4.3.2 + - uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 id: upload-diff if: >- ${{ (steps.files_changed.outputs.files_changed == 'true') && @@ -199,7 +199,7 @@ runs: echo 'Suggestions can only be added near to lines changed in this PR.' echo 'If any fixes can be added as code suggestions, they will be added shortly from another workflow.' } >> "${GITHUB_STEP_SUMMARY}" - - uses: actions/upload-artifact@1746f4ab65b179e0ea60a494b83293b640dd5bba # v4.3.2 + - uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 id: upload-changes if: >- ${{ always() && diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index 9dd0b1a9742..a33c92b709b 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -74,7 +74,7 @@ jobs: nc_spm_full_v2alpha2.tar.gz" - name: Make HTML test report available if: ${{ always() }} - uses: actions/upload-artifact@1746f4ab65b179e0ea60a494b83293b640dd5bba # v4.3.2 + uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 with: name: testreport-macOS path: testreport diff --git a/.github/workflows/python-code-quality.yml b/.github/workflows/python-code-quality.yml index ab44d3abd8a..c570a97008b 100644 --- a/.github/workflows/python-code-quality.yml +++ b/.github/workflows/python-code-quality.yml @@ -102,7 +102,7 @@ jobs: bandit -c pyproject.toml -iii -r . -f sarif -o bandit.sarif --exit-zero - name: Upload Bandit Scan Results - uses: actions/upload-artifact@1746f4ab65b179e0ea60a494b83293b640dd5bba # v4.3.2 + uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 with: name: bandit.sarif path: bandit.sarif @@ -175,7 +175,7 @@ jobs: cp -rp dist.$ARCH/docs/html/libpython sphinx-grass - name: Make Sphinx documentation available - uses: actions/upload-artifact@1746f4ab65b179e0ea60a494b83293b640dd5bba # v4.3.2 + uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 with: name: sphinx-grass path: sphinx-grass diff --git a/.github/workflows/ubuntu.yml b/.github/workflows/ubuntu.yml index 032ba3391c7..6243b7dde00 100644 --- a/.github/workflows/ubuntu.yml +++ b/.github/workflows/ubuntu.yml @@ -151,7 +151,7 @@ jobs: - name: Make HTML test report available if: ${{ always() }} - uses: actions/upload-artifact@1746f4ab65b179e0ea60a494b83293b640dd5bba # v4.3.2 + uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 with: name: testreport-${{ matrix.os }}-${{ matrix.config }}-${{ matrix.extra-include }} path: testreport From 8a90595bc1467b807d2e7f77c2a138b0aae309cc Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 22 Apr 2024 19:14:46 -0400 Subject: [PATCH 13/27] CI(deps): Update actions/download-artifact action to v4.1.6 (#3645) --- .github/workflows/post-pr-reviews.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/post-pr-reviews.yml b/.github/workflows/post-pr-reviews.yml index 9bc2997c076..729e501fd95 100644 --- a/.github/workflows/post-pr-reviews.yml +++ b/.github/workflows/post-pr-reviews.yml @@ -19,7 +19,7 @@ jobs: steps: - name: Create a .git directory needed by reviewdog run: git init - - uses: actions/download-artifact@8caf195ad4b1dee92908e23f56eeb0696f1dd42d # v4.1.5 + - uses: actions/download-artifact@9c19ed7fe5d278cd354c7dfd5d3b88589c7e2395 # v4.1.6 id: diff continue-on-error: true with: From 48038f744c3d8ecb9d9ab8c2b9fb95cba16338f2 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 22 Apr 2024 19:19:53 -0400 Subject: [PATCH 14/27] CI(deps): Update actions/checkout digest to 1d96c77 (v4.1.3) (#3639) --- .github/workflows/additional_checks.yml | 2 +- .github/workflows/codeql-analysis.yml | 2 +- .github/workflows/create_release_draft.yml | 2 +- .github/workflows/docker.yml | 2 +- .github/workflows/gcc.yml | 2 +- .github/workflows/macos.yml | 2 +- .github/workflows/osgeo4w.yml | 2 +- .github/workflows/pytest.yml | 2 +- .github/workflows/python-code-quality.yml | 2 +- .github/workflows/super-linter.yml | 2 +- .github/workflows/ubuntu.yml | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) diff --git a/.github/workflows/additional_checks.yml b/.github/workflows/additional_checks.yml index 180d8c23ab4..4e8108b86ac 100644 --- a/.github/workflows/additional_checks.yml +++ b/.github/workflows/additional_checks.yml @@ -27,7 +27,7 @@ jobs: steps: - name: Checkout repository contents - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 + uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3 with: fetch-depth: 31 diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 9a97d72c02e..479ed6ec4da 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -42,7 +42,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 + uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3 - name: Set up Python uses: actions/setup-python@82c7e631bb3cdc910f68e0081d67478d79c6982d # v5.1.0 with: diff --git a/.github/workflows/create_release_draft.yml b/.github/workflows/create_release_draft.yml index 4a1bdfb0c94..a8b143b77fb 100644 --- a/.github/workflows/create_release_draft.yml +++ b/.github/workflows/create_release_draft.yml @@ -28,7 +28,7 @@ jobs: contents: write steps: - name: Checks-out repository - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 + uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3 with: ref: ${{ github.ref }} fetch-depth: 0 diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index e8616b01718..d2b2d6605ab 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -49,7 +49,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 + uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3 with: fetch-depth: 0 - name: Docker meta diff --git a/.github/workflows/gcc.yml b/.github/workflows/gcc.yml index a7e1963bd16..2816fa14250 100644 --- a/.github/workflows/gcc.yml +++ b/.github/workflows/gcc.yml @@ -35,7 +35,7 @@ jobs: fail-fast: false steps: - - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 + - uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3 - name: Get dependencies run: | sudo apt-get update -y diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index a33c92b709b..1e834e50aad 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -38,7 +38,7 @@ jobs: /usr/bin/sudo /usr/bin/find /usr/local /opt/homebrew -mindepth 1 -maxdepth 1 \ -type f -print -delete hash -r - - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 + - uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3 - name: Setup Mamba uses: mamba-org/setup-micromamba@422500192359a097648154e8db4e39bdb6c6eed7 # v1.8.1 with: diff --git a/.github/workflows/osgeo4w.yml b/.github/workflows/osgeo4w.yml index e8bfecc532b..356b232095b 100644 --- a/.github/workflows/osgeo4w.yml +++ b/.github/workflows/osgeo4w.yml @@ -32,7 +32,7 @@ jobs: run: | git config --global core.autocrlf false git config --global core.eol lf - - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 + - uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3 - uses: msys2/setup-msys2@cc11e9188b693c2b100158c3322424c4cc1dadea # v2.22.0 with: path-type: inherit diff --git a/.github/workflows/pytest.yml b/.github/workflows/pytest.yml index caa530f90e1..03cf1e92133 100644 --- a/.github/workflows/pytest.yml +++ b/.github/workflows/pytest.yml @@ -31,7 +31,7 @@ jobs: runs-on: ${{ matrix.os }} steps: - - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 + - uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3 - name: Set up Python uses: actions/setup-python@82c7e631bb3cdc910f68e0081d67478d79c6982d # v5.1.0 diff --git a/.github/workflows/python-code-quality.yml b/.github/workflows/python-code-quality.yml index c570a97008b..7cd8cb316c7 100644 --- a/.github/workflows/python-code-quality.yml +++ b/.github/workflows/python-code-quality.yml @@ -49,7 +49,7 @@ jobs: echo Pylint: ${{ matrix.pylint-version }} echo Bandit: ${{matrix.bandit-version}} - - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 + - uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3 - name: Set up Python uses: actions/setup-python@82c7e631bb3cdc910f68e0081d67478d79c6982d # v5.1.0 diff --git a/.github/workflows/super-linter.yml b/.github/workflows/super-linter.yml index 6712d5d9323..34086aa18ff 100644 --- a/.github/workflows/super-linter.yml +++ b/.github/workflows/super-linter.yml @@ -28,7 +28,7 @@ jobs: statuses: write steps: - - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 + - uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3 with: # super-linter needs the full git history to get the # list of files that changed across commits diff --git a/.github/workflows/ubuntu.yml b/.github/workflows/ubuntu.yml index 6243b7dde00..bce6b0bb089 100644 --- a/.github/workflows/ubuntu.yml +++ b/.github/workflows/ubuntu.yml @@ -61,7 +61,7 @@ jobs: fail-fast: false steps: - - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 + - uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3 - name: Invert inclusion list to an exclusion list id: get-exclude From 61a171ecd09fb82de204ac276d6b0bf9adb2dcd9 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 23 Apr 2024 00:09:09 -0400 Subject: [PATCH 15/27] CI(deps): Update github/codeql-action action to v3.25.2 (#3648) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/codeql-analysis.yml | 4 ++-- .github/workflows/python-code-quality.yml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 479ed6ec4da..02e9c8ea3fb 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -56,7 +56,7 @@ jobs: sudo apt-get install -y --no-install-recommends --no-install-suggests - name: Initialize CodeQL - uses: github/codeql-action/init@c7f9125735019aa87cfc361530512d50ea439c71 # v3.25.1 + uses: github/codeql-action/init@8f596b4ae3cb3c588a5c46780b86dd53fef16c52 # v3.25.2 with: languages: ${{ matrix.language }} config-file: ./.github/codeql/codeql-config.yml @@ -81,6 +81,6 @@ jobs: run: .github/workflows/build_ubuntu-22.04.sh "${HOME}/install" - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@c7f9125735019aa87cfc361530512d50ea439c71 # v3.25.1 + uses: github/codeql-action/analyze@8f596b4ae3cb3c588a5c46780b86dd53fef16c52 # v3.25.2 with: category: "/language:${{matrix.language}}" diff --git a/.github/workflows/python-code-quality.yml b/.github/workflows/python-code-quality.yml index 7cd8cb316c7..2fdf7766a73 100644 --- a/.github/workflows/python-code-quality.yml +++ b/.github/workflows/python-code-quality.yml @@ -108,7 +108,7 @@ jobs: path: bandit.sarif - name: Upload SARIF File into Security Tab - uses: github/codeql-action/upload-sarif@c7f9125735019aa87cfc361530512d50ea439c71 # v3.25.1 + uses: github/codeql-action/upload-sarif@8f596b4ae3cb3c588a5c46780b86dd53fef16c52 # v3.25.2 with: sarif_file: bandit.sarif From 5661bad9abc43754764dc5fb630dc65c8afa6845 Mon Sep 17 00:00:00 2001 From: Huidae Cho Date: Tue, 23 Apr 2024 03:02:46 -0700 Subject: [PATCH 16/27] libgis: Rename ap_copy to aq for G_aprintf (#3651) --- lib/gis/aprintf.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/gis/aprintf.c b/lib/gis/aprintf.c index 67cde7f97a5..2c7b235f214 100644 --- a/lib/gis/aprintf.c +++ b/lib/gis/aprintf.c @@ -199,11 +199,11 @@ static int oaprintf(struct options *opts, const char *format, va_list ap) while (*++c && *q != *c) ; if (*c) { - va_list ap_copy; + va_list aq; char tmp; /* copy ap for ovprintf() */ - va_copy(ap_copy, ap); + va_copy(aq, ap); /* found a conversion specifier */ if (*c == 's') { @@ -254,7 +254,7 @@ static int oaprintf(struct options *opts, const char *format, va_list ap) } if (*p_spec) { /* illegal string specifier? */ - va_end(ap_copy); + va_end(aq); *(q + 1) = 0; G_fatal_error( _("Failed to parse string specifier: %s"), p); @@ -290,7 +290,7 @@ static int oaprintf(struct options *opts, const char *format, va_list ap) if (use_ovprintf) { tmp = *(q + 1); *(q + 1) = 0; - nbytes += ovprintf(opts, p, ap_copy); + nbytes += ovprintf(opts, p, aq); *(q + 1) = tmp; } } @@ -298,7 +298,7 @@ static int oaprintf(struct options *opts, const char *format, va_list ap) /* else use ovprintf() for non-string specifiers */ tmp = *(q + 1); *(q + 1) = 0; - nbytes += ovprintf(opts, p, ap_copy); + nbytes += ovprintf(opts, p, aq); *(q + 1) = tmp; /* once ap is passed to another function that calls @@ -345,7 +345,7 @@ static int oaprintf(struct options *opts, const char *format, va_list ap) /* otherwise, no argument is required for m% */ } } - va_end(ap_copy); + va_end(aq); break; } else if (p_spec - spec < SPEC_BUF_SIZE - 2) From e354fa62ae20273ca7ebaf0be96cf182d540e5ce Mon Sep 17 00:00:00 2001 From: Veronica Andreo Date: Tue, 23 Apr 2024 06:04:22 -0400 Subject: [PATCH 17/27] g.gui.tplot manual: specify size option units (#3643) * g.gui.tplot manual: specify size option units * Update gui/wxpython/tplot/g.gui.tplot.py Co-authored-by: Anna Petrasova --------- Co-authored-by: Anna Petrasova --- gui/wxpython/tplot/g.gui.tplot.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gui/wxpython/tplot/g.gui.tplot.py b/gui/wxpython/tplot/g.gui.tplot.py index ae07e0e4022..1a411dabf31 100755 --- a/gui/wxpython/tplot/g.gui.tplot.py +++ b/gui/wxpython/tplot/g.gui.tplot.py @@ -104,7 +104,7 @@ # %option # % key: size # % type: string -# % label: The size for output image +# % label: Size of output image as width,height in pixels # % description: It works only with output parameter # % required: no # %end From 0b248eff74ee3d2ccc1d24ca62a0a04b4daf5e64 Mon Sep 17 00:00:00 2001 From: Huidae Cho Date: Tue, 23 Apr 2024 07:01:32 -0700 Subject: [PATCH 18/27] g.mkfontcap: Replace -o with --overwrite; Add a renamed flag warning (#3649) * g.mkfontcap: Replace -o with --overwrite; Add a renamed flag warning * Replace all g.mkfontcap -o with --overwrite --- binaryInstall.src | 2 +- general/g.mkfontcap/main.c | 19 +++++++------------ lib/driver/font2.c | 2 +- lib/gis/renamed_options | 2 ++ mswindows/GRASS-Installer.nsi.tmpl | 2 +- mswindows/osgeo4w/postinstall.bat | 2 +- 6 files changed, 13 insertions(+), 16 deletions(-) diff --git a/binaryInstall.src b/binaryInstall.src index c9736d7c95a..5ab008dd796 100755 --- a/binaryInstall.src +++ b/binaryInstall.src @@ -319,7 +319,7 @@ echo"" echo "Generating display font configuration file..." -GISBASE="$DESTDIR" GISRC=junk LD_LIBRARY_PATH_VAR="${DESTDIR}/lib:$LD_LIBRARY_PATH_VAR" "${DESTDIR}/bin/g.mkfontcap" -o +GISBASE="$DESTDIR" GISRC=junk LD_LIBRARY_PATH_VAR="${DESTDIR}/lib:$LD_LIBRARY_PATH_VAR" "${DESTDIR}/bin/g.mkfontcap" --overwrite echo"" diff --git a/general/g.mkfontcap/main.c b/general/g.mkfontcap/main.c index 0a4a80fbae6..8122ba158e5 100644 --- a/general/g.mkfontcap/main.c +++ b/general/g.mkfontcap/main.c @@ -5,7 +5,7 @@ * PURPOSE: Generates the font configuration file by scanning various * directories for GRASS stroke and Freetype-compatible fonts. * - * COPYRIGHT: (C) 2007-2015 by the GRASS Development Team + * COPYRIGHT: (C) 2007-2024 by the GRASS Development Team * * This program is free software under the GNU General Public * License (>=v2). Read the file COPYING that comes with GRASS @@ -47,7 +47,7 @@ static int compare_fonts(const void *, const void *); int main(int argc, char *argv[]) { - struct Flag *tostdout, *overwrite; + struct Flag *tostdout; struct Option *extradirs; struct GModule *module; @@ -65,11 +65,6 @@ int main(int argc, char *argv[]) "Generates the font configuration file by scanning various directories " "for fonts."); - overwrite = G_define_flag(); - overwrite->key = 'o'; - overwrite->description = - _("Overwrite font configuration file if already existing"); - tostdout = G_define_flag(); tostdout->key = 's'; tostdout->description = @@ -99,11 +94,11 @@ int main(int argc, char *argv[]) G_asprintf(&fontcapfile, "%s/etc/fontcap", gisbase); if (!access(fontcapfile, F_OK)) { /* File exists? */ - if (!overwrite->answer) - G_fatal_error( - _("Fontcap file %s already exists; use -%c flag if you " - "wish to overwrite it"), - fontcapfile, overwrite->key); + if (!G_get_overwrite()) + G_fatal_error(_("Fontcap file %s already exists; use " + "--overwrite flag if you " + "wish to overwrite it"), + fontcapfile); } } diff --git a/lib/driver/font2.c b/lib/driver/font2.c index 7b80a5e8870..67e26572542 100644 --- a/lib/driver/font2.c +++ b/lib/driver/font2.c @@ -146,7 +146,7 @@ static void read_fontmap(const char *name) fp = fopen(buf, "r"); if (!fp) { G_warning("Unable to open font map '%s': %s. " - "Try running 'g.mkfontcap -o'", + "Try running 'g.mkfontcap --overwrite'", buf, strerror(errno)); return; } diff --git a/lib/gis/renamed_options b/lib/gis/renamed_options index 965168b29d9..00893c68c83 100644 --- a/lib/gis/renamed_options +++ b/lib/gis/renamed_options @@ -95,6 +95,8 @@ g.mapset|gisdbase:dbase g.mapsets|addmapset:operation g.mapsets|removemapset:operation g.mapsets|measure:method +# g.mkfontcap +g.mkfontcap|-o:--overwrite # g.pnmcomp g.pnmcomp|background:bgcolor ################################### diff --git a/mswindows/GRASS-Installer.nsi.tmpl b/mswindows/GRASS-Installer.nsi.tmpl index 47e7d6a025a..2b2722a5083 100644 --- a/mswindows/GRASS-Installer.nsi.tmpl +++ b/mswindows/GRASS-Installer.nsi.tmpl @@ -557,7 +557,7 @@ Section "GRASS" SecGRASS FileWrite $0 'set GISRC=dummy$\r$\n' FileWrite $0 '$\r$\n' FileWrite $0 'rem run g.mkfontcap outside a grass session$\r$\n' - FileWrite $0 '"%GISBASE%\bin\g.mkfontcap.exe" -o$\r$\n' + FileWrite $0 '"%GISBASE%\bin\g.mkfontcap.exe" --overwrite$\r$\n' FileWrite $0 'exit$\r$\n' FileClose $0 done_create_run_gmkfontcap.bat: diff --git a/mswindows/osgeo4w/postinstall.bat b/mswindows/osgeo4w/postinstall.bat index e9f75cecfdf..61d2d98b7d4 100644 --- a/mswindows/osgeo4w/postinstall.bat +++ b/mswindows/osgeo4w/postinstall.bat @@ -24,6 +24,6 @@ rem GISRC must be set set GISRC=dummy rem run g.mkfontcap outside a GRASS session -"%GISBASE%\bin\g.mkfontcap.exe" -o +"%GISBASE%\bin\g.mkfontcap.exe" --overwrite del "%BATCH%.tmpl From f8115df1219e784a7136e7609f4c9bb16d928e2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Edouard=20Choini=C3=A8re?= <27212526+echoix@users.noreply.github.com> Date: Tue, 23 Apr 2024 10:45:15 -0400 Subject: [PATCH 19/27] python: Update black to 24.4.0 (#3545) * CI(black): Upgrade black to 24.3.0 (including Jupyter notebooks) * python: Require black version 24 * python: Update black target-version * python(black): Use extend-exclude instead of overriding exclude * python: Use black's default include pattern to format Jupyter notebooks * pre-commit: Update black hook to 24.3.0 (including Jupyter notebooks) * python: Format python files with Black 24.3.0 * python: Format Jupyter notebooks with Black 24.3.0 * python: Format new files with black * Update black to 24.4.0 * wxGUI/wxplot: Format profile with black --- .github/workflows/python-code-quality.yml | 4 +- .pre-commit-config.yaml | 7 +- doc/notebooks/hydrology.ipynb | 125 ++++++++++++------ doc/notebooks/jupyter_example.ipynb | 8 +- doc/notebooks/jupyter_tutorial.ipynb | 20 +-- doc/notebooks/parallelization_tutorial.ipynb | 1 + doc/notebooks/scripting_example.ipynb | 12 +- doc/notebooks/solar_potential.ipynb | 43 +++++- doc/notebooks/temporal.ipynb | 12 +- doc/notebooks/viewshed_analysis.ipynb | 13 +- general/g.mapsets/tests/conftest.py | 1 - general/g.region/testsuite/test_g_region.py | 1 + gui/wxpython/animation/controller.py | 1 + gui/wxpython/animation/data.py | 1 + gui/wxpython/animation/frame.py | 1 + gui/wxpython/animation/provider.py | 23 ++-- gui/wxpython/animation/temporal_manager.py | 8 +- gui/wxpython/animation/toolbars.py | 1 + gui/wxpython/animation/utils.py | 1 + gui/wxpython/core/treemodel.py | 1 + gui/wxpython/core/ws.py | 1 + gui/wxpython/datacatalog/dialogs.py | 1 - gui/wxpython/datacatalog/tree.py | 1 + gui/wxpython/gcp/statusbar.py | 1 - gui/wxpython/gui_core/menu.py | 1 + gui/wxpython/gui_core/preferences.py | 12 +- gui/wxpython/gui_core/pystc.py | 1 - gui/wxpython/gui_core/query.py | 1 + gui/wxpython/iclass/dialogs.py | 1 + gui/wxpython/icons/grass_icons.py | 1 + gui/wxpython/image2target/ii2t_statusbar.py | 1 - gui/wxpython/iscatt/controllers.py | 1 + gui/wxpython/iscatt/frame.py | 1 - gui/wxpython/iscatt/iscatt_core.py | 1 + gui/wxpython/iscatt/plots.py | 1 + gui/wxpython/iscatt/toolbars.py | 1 + gui/wxpython/location_wizard/dialogs.py | 1 + gui/wxpython/location_wizard/wizard.py | 1 + gui/wxpython/mapwin/decorations.py | 1 - gui/wxpython/mapwin/graphics.py | 1 - gui/wxpython/nviz/mapwindow.py | 28 ++-- gui/wxpython/photo2image/ip2i_statusbar.py | 1 - gui/wxpython/psmap/dialogs.py | 24 ++-- gui/wxpython/psmap/frame.py | 8 +- gui/wxpython/psmap/utils.py | 1 + gui/wxpython/rdigit/controller.py | 1 + gui/wxpython/rlisetup/functions.py | 1 + gui/wxpython/startup/guiutils.py | 1 - gui/wxpython/vdigit/toolbars.py | 1 + gui/wxpython/vdigit/wxdigit.py | 1 - gui/wxpython/vdigit/wxdisplay.py | 1 - gui/wxpython/vnet/toolbars.py | 2 +- gui/wxpython/vnet/vnet_data.py | 1 + gui/wxpython/wxplot/profile.py | 8 +- imagery/i.pca/testsuite/test_pca.py | 1 + imagery/i.segment/testsuite/test_isegment.py | 1 + .../testsuite/test_i_signatures.py | 1 + .../testsuite/test_i_svm_predict.py | 1 + .../i.svm.train/testsuite/test_i_svm_train.py | 1 + imagery/i.vi/testsuite/test_vi.py | 1 + lib/gis/testsuite/gis_lib_env_test.py | 1 + lib/imagery/testsuite/test_imagery_find.py | 1 + lib/imagery/testsuite/test_imagery_sigfile.py | 7 +- .../test_imagery_signature_management.py | 1 + .../testsuite/test_imagery_sigsetfile.py | 1 + lib/raster/testsuite/test_raster_metadata.py | 1 + lib/raster3d/testsuite/raster3d_lib_test.py | 1 + man/parser_standard_options.py | 1 + pyproject.toml | 23 +--- python/grass/grassdb/create.py | 1 - python/grass/grassdb/manage.py | 1 - python/grass/gunittest/multireport.py | 1 - python/grass/gunittest/runner.py | 1 - .../gunittest/testsuite/test_assertions.py | 1 - .../gunittest/testsuite/test_checkers.py | 1 - python/grass/imaging/operations.py | 1 - python/grass/jupyter/tests/seriesmap_test.py | 1 - .../grass/jupyter/tests/timeseriesmap_test.py | 1 - python/grass/pydispatch/dispatcher.py | 1 + python/grass/pydispatch/robust.py | 1 + python/grass/pydispatch/robustapply.py | 1 + python/grass/pydispatch/signal.py | 1 - python/grass/pygrass/gis/region.py | 1 + python/grass/pygrass/messages/__init__.py | 1 + python/grass/pygrass/modules/grid/patch.py | 1 + python/grass/pygrass/modules/grid/split.py | 1 + .../pygrass/modules/interface/__init__.py | 1 + python/grass/pygrass/modules/interface/env.py | 1 + .../pygrass/modules/interface/parameter.py | 9 +- .../modules/interface/testsuite/test_flag.py | 1 + .../interface/testsuite/test_modules.py | 1 + .../interface/testsuite/test_parameter.py | 1 + .../pygrass/modules/interface/typedict.py | 1 + .../testsuite/test_import_isolation.py | 1 + python/grass/pygrass/raster/abstract.py | 1 + python/grass/pygrass/raster/category.py | 1 + python/grass/pygrass/raster/history.py | 1 + python/grass/pygrass/raster/raster_type.py | 1 + python/grass/pygrass/raster/rowio.py | 1 + python/grass/pygrass/raster/segment.py | 1 + .../pygrass/raster/testsuite/test_numpy.py | 1 + python/grass/pygrass/shell/conversion.py | 1 - python/grass/pygrass/vector/abstract.py | 1 + python/grass/pygrass/vector/basic.py | 1 + python/grass/pygrass/vector/find.py | 1 + python/grass/pygrass/vector/geometry.py | 1 + .../pygrass/vector/testsuite/test_filters.py | 1 + .../pygrass/vector/testsuite/test_geometry.py | 1 + .../vector/testsuite/test_geometry_attrs.py | 1 + .../pygrass/vector/testsuite/test_table.py | 1 + .../pygrass/vector/testsuite/test_vector.py | 1 + .../pygrass/vector/testsuite/test_vector3d.py | 1 + python/grass/script/task.py | 1 + python/grass/script/vector.py | 1 + python/grass/temporal/abstract_dataset.py | 1 + python/grass/temporal/abstract_map_dataset.py | 1 + .../temporal/abstract_space_time_dataset.py | 1 + python/grass/temporal/base.py | 1 + python/grass/temporal/core.py | 1 + python/grass/temporal/datetime_math.py | 1 + python/grass/temporal/extract.py | 1 + python/grass/temporal/factory.py | 1 + python/grass/temporal/gui_support.py | 1 + python/grass/temporal/list_stds.py | 12 +- python/grass/temporal/mapcalc.py | 1 + python/grass/temporal/metadata.py | 1 + python/grass/temporal/open_stds.py | 1 + python/grass/temporal/register.py | 1 + python/grass/temporal/sampling.py | 1 + python/grass/temporal/space_time_datasets.py | 1 + python/grass/temporal/spatial_extent.py | 1 + .../spatial_topology_dataset_connector.py | 1 + .../temporal/spatio_temporal_relationships.py | 1 + python/grass/temporal/temporal_algebra.py | 12 +- python/grass/temporal/temporal_extent.py | 1 + python/grass/temporal/temporal_granularity.py | 1 + python/grass/temporal/temporal_operator.py | 1 + .../temporal/temporal_raster3d_algebra.py | 1 + .../temporal/temporal_raster_base_algebra.py | 1 + .../temporal_topology_dataset_connector.py | 1 + .../grass/temporal/temporal_vector_algebra.py | 1 + .../unittests_temporal_raster3d_algebra.py | 1 - python/grass/temporal/unit_tests.py | 1 + python/grass/temporal/univar_statistics.py | 1 + raster/r.basins.fill/testsuite/testrbf.py | 1 + .../r.external/testsuite/test_r_external.py | 1 + .../r.gwflow/testsuite/validation_7x7_grid.py | 1 + raster/r.horizon/testsuite/test_r_horizon.py | 1 + .../r.in.ascii/testsuite/test_r_in_ascii.py | 1 + raster/r.in.gdal/testsuite/test_r_in_gdal.py | 1 + raster/r.info/testsuite/test_r_info.py | 1 + .../testsuite/test_random_cells.py | 1 - raster/r.random/testsuite/testrandom.py | 1 + raster/r.reclass/testsuite/test_r_reclass.py | 1 + .../r.series.interp/testsuite/interp_test.py | 1 + raster/r.support/testsuite/test_r_support.py | 1 + raster/r.texture/testsuite/test_texture.py | 1 + raster/r.tile/testsuite/testrt.py | 1 + raster/r.to.vect/testsuite/test_r_to_vect.py | 1 + raster/r.univar/testsuite/test_r_univar.py | 1 + raster/r.what/testsuite/testrw.py | 1 + raster3d/r3.flow/testsuite/r3flow_test.py | 1 + .../r3.gradient/testsuite/r3gradient_test.py | 1 + .../r.fillnulls/testsuite/test_r_fillnulls.py | 1 + scripts/r.in.wms/srs.py | 1 + scripts/r.in.wms/wms_cap_parsers.py | 1 + .../testsuite/test_rmapcalcsimple.py | 1 + scripts/r.reclass.area/testsuite/testrra.py | 1 + .../testsuite/test_v_rast_stats.py | 1 + .../testsuite/test_aggregation_absolute.py | 1 + .../test_aggregation_absolute_parallel.py | 1 + .../testsuite/test_aggregation_relative.py | 1 + .../t.rast.series/testsuite/test_series.py | 1 + .../testsuite/test_raster3d_algebra.py | 1 - temporal/t.shift/testsuite/test_shift.py | 1 + temporal/t.snap/testsuite/test_snap.py | 1 + .../testsuite/test_support_str3ds.py | 1 + .../t.support/testsuite/test_support_strds.py | 1 + .../t.support/testsuite/test_support_stvds.py | 1 + .../t.unregister/testsuite/test_unregister.py | 1 + vector/v.extract/testsuite/test_v_extract.py | 1 + vector/v.fill.holes/examples.ipynb | 24 ++-- vector/v.in.ogr/testsuite/test_v_in_ogr.py | 1 + vector/v.to.rast/testsuite/test_v_to_rast.py | 1 + vector/v.univar/testsuite/v_univar_test.py | 1 + .../v.vect.stats/testsuite/test_vect_stats.py | 1 + 186 files changed, 410 insertions(+), 197 deletions(-) diff --git a/.github/workflows/python-code-quality.yml b/.github/workflows/python-code-quality.yml index 2fdf7766a73..777637e8322 100644 --- a/.github/workflows/python-code-quality.yml +++ b/.github/workflows/python-code-quality.yml @@ -29,7 +29,7 @@ jobs: - os: ubuntu-22.04 python-version: "3.10" min-python-version: "3.7" - black-version: "23.1.0" + black-version: "24.4.0" flake8-version: "3.9.2" pylint-version: "2.12.2" bandit-version: "1.7.8" @@ -60,7 +60,7 @@ jobs: run: python -m pip install --upgrade pip - name: Install Black only - run: pip install black==${{ matrix.black-version }} + run: pip install black[jupyter]==${{ matrix.black-version }} - name: Run Black run: black . diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 61509b4280b..65cb46a2f53 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -39,10 +39,11 @@ repos: rev: v0.33.0 hooks: - id: markdownlint - - repo: https://github.com/psf/black - rev: 23.1.0 + # Using this mirror lets us use mypyc-compiled black, which is about 2x faster + - repo: https://github.com/psf/black-pre-commit-mirror + rev: 24.4.0 hooks: - - id: black + - id: black-jupyter exclude: | (?x)^( python/libgrass_interface_generator/ diff --git a/doc/notebooks/hydrology.ipynb b/doc/notebooks/hydrology.ipynb index f19ce35c436..b9e23acf3c1 100644 --- a/doc/notebooks/hydrology.ipynb +++ b/doc/notebooks/hydrology.ipynb @@ -69,7 +69,9 @@ "\n", "# Add a raster, vector and legend to the map\n", "elev_map.d_rast(map=\"elevation\")\n", - "elev_map.d_legend(raster=\"elevation\", at=(65, 90, 85, 88), fontsize=12, flags=\"b\", title=\"DTM\")\n", + "elev_map.d_legend(\n", + " raster=\"elevation\", at=(65, 90, 85, 88), fontsize=12, flags=\"b\", title=\"DTM\"\n", + ")\n", "\n", "# Display map\n", "elev_map.show()" @@ -90,9 +92,27 @@ "metadata": {}, "outputs": [], "source": [ - "gs.run_command(\"r.fill.dir\", input=\"elevation\", output=\"elev_fill1\", direction=\"dir1\", areas=\"area1\")\n", - "gs.run_command(\"r.fill.dir\", input=\"elev_fill1\", output=\"elev_fill2\", direction=\"dir2\", areas=\"area2\")\n", - "gs.run_command(\"r.fill.dir\", input=\"elev_fill2\", output=\"elev_fill3\", direction=\"dir3\", areas=\"area3\")\n", + "gs.run_command(\n", + " \"r.fill.dir\",\n", + " input=\"elevation\",\n", + " output=\"elev_fill1\",\n", + " direction=\"dir1\",\n", + " areas=\"area1\",\n", + ")\n", + "gs.run_command(\n", + " \"r.fill.dir\",\n", + " input=\"elev_fill1\",\n", + " output=\"elev_fill2\",\n", + " direction=\"dir2\",\n", + " areas=\"area2\",\n", + ")\n", + "gs.run_command(\n", + " \"r.fill.dir\",\n", + " input=\"elev_fill2\",\n", + " output=\"elev_fill3\",\n", + " direction=\"dir3\",\n", + " areas=\"area3\",\n", + ")\n", "gs.mapcalc(\"depr_bin = if((elevation-elev_fill3) < 0., 1, null())\")\n", "gs.run_command(\"r.colors\", map=\"depr_bin\", color=\"blues\")" ] @@ -129,13 +149,15 @@ "metadata": {}, "outputs": [], "source": [ - "gs.run_command(\"r.watershed\", \n", - " elevation=\"elevation@PERMANENT\",\n", - " drainage=\"drainage\", # Drainage Direction\n", - " accumulation=\"flowacc\", # Flow Accumulation\n", - " basin=\"watersheds\",\n", - " stream=\"streams\",\n", - " threshold=80000)\n", + "gs.run_command(\n", + " \"r.watershed\",\n", + " elevation=\"elevation@PERMANENT\",\n", + " drainage=\"drainage\", # Drainage Direction\n", + " accumulation=\"flowacc\", # Flow Accumulation\n", + " basin=\"watersheds\",\n", + " stream=\"streams\",\n", + " threshold=80000,\n", + ")\n", "\n", "# Convert streams raster to vector\n", "gs.run_command(\"r.to.vect\", input=\"streams\", output=\"streams\", type=\"line\")" @@ -160,7 +182,7 @@ "\n", "# We can modify with color table for rasters with `r.colors`.\n", "# Note that if the raster is located in a different mapset (for example,\n", - "# elevation is in PERMANENT, not user1), the `r.colors` will not change \n", + "# elevation is in PERMANENT, not user1), the `r.colors` will not change\n", "# the color in InteractiveMap.\n", "gs.run_command(\"r.colors\", map=\"drainage\", color=\"aspect\")\n", "\n", @@ -193,13 +215,19 @@ "outputs": [], "source": [ "# Count cells in each watershed\n", - "gs.run_command(\"r.stats.zonal\", base=\"watersheds\", cover=\"elevation\", method=\"count\", output=\"watersheds_count\")\n", + "gs.run_command(\n", + " \"r.stats.zonal\",\n", + " base=\"watersheds\",\n", + " cover=\"elevation\",\n", + " method=\"count\",\n", + " output=\"watersheds_count\",\n", + ")\n", "\n", "# Get projection resolution\n", - "proj=gs.parse_command(\"g.region\", flags=\"m\")\n", + "proj = gs.parse_command(\"g.region\", flags=\"m\")\n", "\n", "# Multiply N-S resollution by E-W resolution to get cell area\n", - "cell_area = float(proj[\"nsres\"])*float(proj[\"ewres\"])\n", + "cell_area = float(proj[\"nsres\"]) * float(proj[\"ewres\"])\n", "\n", "# Calculate watersheds areas and convert from m2 to km2\n", "gs.mapcalc(\"'watershed_area' = float('watersheds_count'*{})/1000000\".format(cell_area))" @@ -220,18 +248,20 @@ "source": [ "# Display a map of watershed areas.\n", "gs.run_command(\"r.colors\", map=\"watershed_area\", color=\"plasma\")\n", - " \n", + "\n", "watershed_map = gj.Map()\n", "watershed_map.d_rast(map=\"watershed_area\")\n", - "watershed_map.d_legend(raster=\"watershed_area\",\n", - " bgcolor=\"none\",\n", - " color=\"black\",\n", - " border_color=\"none\",\n", - " at=(3, 40, 84, 88),\n", - " lines=2,\n", - " fontsize=15,\n", - " title=\"Area\",\n", - " units=\" km2\")\n", + "watershed_map.d_legend(\n", + " raster=\"watershed_area\",\n", + " bgcolor=\"none\",\n", + " color=\"black\",\n", + " border_color=\"none\",\n", + " at=(3, 40, 84, 88),\n", + " lines=2,\n", + " fontsize=15,\n", + " title=\"Area\",\n", + " units=\" km2\",\n", + ")\n", "watershed_map.show()" ] }, @@ -265,7 +295,14 @@ "# Display slope map\n", "slope_map = gj.Map()\n", "slope_map.d_rast(map=\"slope\")\n", - "slope_map.d_legend(raster=\"slope\", at=(65, 90, 85, 90), fontsize=15, flags=\"b\", title=\"Slope\", units=\"°\")\n", + "slope_map.d_legend(\n", + " raster=\"slope\",\n", + " at=(65, 90, 85, 90),\n", + " fontsize=15,\n", + " flags=\"b\",\n", + " title=\"Slope\",\n", + " units=\"°\",\n", + ")\n", "slope_map.show()" ] }, @@ -284,14 +321,16 @@ "source": [ "separator = \"|\"\n", "\n", - "columns = defaultdict(list) # each value in each column is appended to a list\n", + "columns = defaultdict(list) # each value in each column is appended to a list\n", "\n", - "text = gs.read_command(\"r.univar\", map=\"elevation\", zones=\"watersheds\", separator=separator, flags=\"t\")\n", + "text = gs.read_command(\n", + " \"r.univar\", map=\"elevation\", zones=\"watersheds\", separator=separator, flags=\"t\"\n", + ")\n", "reader = csv.DictReader(text.splitlines(), delimiter=separator)\n", - "for row in reader: # read a row as {column1: value1, column2: value2,...}\n", - " for (k,v) in row.items(): # go over each column name and value \n", - " columns[k].append(v) # append the value into the appropriate list\n", - " # based on column name k\n", + "for row in reader: # read a row as {column1: value1, column2: value2,...}\n", + " for k, v in row.items(): # go over each column name and value\n", + " columns[k].append(v) # append the value into the appropriate list\n", + " # based on column name k\n", "\n", "watersheds = columns[\"zone\"]\n", "means = np.array(columns[\"mean\"], dtype=np.float32)\n", @@ -333,7 +372,9 @@ "outputs": [], "source": [ "# Convert to vector\n", - "gs.run_command(\"r.to.vect\", flags=\"s\", input=\"watersheds\", output=\"watersheds_vector\", type=\"area\")" + "gs.run_command(\n", + " \"r.to.vect\", flags=\"s\", input=\"watersheds\", output=\"watersheds_vector\", type=\"area\"\n", + ")" ] }, { @@ -345,14 +386,16 @@ "# Display\n", "watershed_vect_map = gj.Map()\n", "watershed_vect_map.d_rast(map=\"elevation\")\n", - "watershed_vect_map.d_vect(map=\"watersheds_vector\",\n", - " fill_color=\"none\",\n", - " width=1.5,\n", - " color=\"black\",\n", - " attribute_column=\"value\",\n", - " label_bgcolor=\"black\",\n", - " label_color=\"white\",\n", - " label_size=10)\n", + "watershed_vect_map.d_vect(\n", + " map=\"watersheds_vector\",\n", + " fill_color=\"none\",\n", + " width=1.5,\n", + " color=\"black\",\n", + " attribute_column=\"value\",\n", + " label_bgcolor=\"black\",\n", + " label_color=\"white\",\n", + " label_size=10,\n", + ")\n", "watershed_vect_map.show()" ] } diff --git a/doc/notebooks/jupyter_example.ipynb b/doc/notebooks/jupyter_example.ipynb index a0f660b5cd3..48628e08263 100644 --- a/doc/notebooks/jupyter_example.ipynb +++ b/doc/notebooks/jupyter_example.ipynb @@ -64,7 +64,9 @@ "outputs": [], "source": [ "gs.parse_command(\"g.region\", raster=\"lakes\", flags=\"pg\")\n", - "gs.run_command(\"r.buffer\", input=\"lakes\", output=\"lakes_buff\", distances=[60, 120, 240, 500])\n", + "gs.run_command(\n", + " \"r.buffer\", input=\"lakes\", output=\"lakes_buff\", distances=[60, 120, 240, 500]\n", + ")\n", "\n", "# Start a Map\n", "r_buffer_map = gj.Map()\n", @@ -101,7 +103,9 @@ "v_buffer_map = gj.Map()\n", "\n", "# Add vector layers and legend\n", - "v_buffer_map.d_vect(map=\"boundary_state\", fill_color=\"#5A91ED\", legend_label=\"State boundary\")\n", + "v_buffer_map.d_vect(\n", + " map=\"boundary_state\", fill_color=\"#5A91ED\", legend_label=\"State boundary\"\n", + ")\n", "v_buffer_map.d_vect(map=\"buffer\", fill_color=\"#F8766D\", legend_label=\"Inner portion\")\n", "v_buffer_map.d_legend_vect(at=(10, 35))\n", "\n", diff --git a/doc/notebooks/jupyter_tutorial.ipynb b/doc/notebooks/jupyter_tutorial.ipynb index 8213ea970ca..73d656905f7 100644 --- a/doc/notebooks/jupyter_tutorial.ipynb +++ b/doc/notebooks/jupyter_tutorial.ipynb @@ -142,7 +142,7 @@ "source": [ "# Then, we return to the first instance and continue to modify and display it\n", "# Notice that layers a drawn in the order they are added\n", - "example_map.run(\"d.vect\", map = \"zipcodes\", color=\"red\", fill_color=\"none\")\n", + "example_map.run(\"d.vect\", map=\"zipcodes\", color=\"red\", fill_color=\"none\")\n", "example_map.show()" ] }, @@ -277,11 +277,11 @@ "metadata": {}, "outputs": [], "source": [ - "import folium \n", + "import folium\n", "\n", "\n", "# Create a map\n", - "m = folium.Map(location=[35.761168,-78.668271], zoom_start=13)\n", + "m = folium.Map(location=[35.761168, -78.668271], zoom_start=13)\n", "\n", "# Create and add elevation layer to map\n", "gj.Raster(\"elevation\", opacity=0.5).add_to(m)\n", @@ -291,7 +291,7 @@ "tooltip = \"Click me!\"\n", "# and add a marker\n", "folium.Marker(\n", - " [35.781608,-78.675800], popup=\"Point of Interest\", tooltip=tooltip\n", + " [35.781608, -78.675800], popup=\"Point of Interest\", tooltip=tooltip\n", ").add_to(m)\n", "\n", "# Display map\n", @@ -313,10 +313,10 @@ "metadata": {}, "outputs": [], "source": [ - "import ipyleaflet \n", + "import ipyleaflet\n", "\n", "# Create map\n", - "m = ipyleaflet.Map(center=[35.761168,-78.668271], zoom=13)\n", + "m = ipyleaflet.Map(center=[35.761168, -78.668271], zoom=13)\n", "\n", "# Create and add elevation layer to map\n", "gj.Raster(\"elevation\", opacity=0.5).add_to(m)\n", @@ -325,12 +325,12 @@ "# Like make a tooltip\n", "title = \"Click me!\"\n", "# and add a marker\n", - "marker = ipyleaflet.Marker(name='marker', location=(35.781608,-78.675800), title=title)\n", + "marker = ipyleaflet.Marker(name=\"marker\", location=(35.781608, -78.675800), title=title)\n", "\n", "# Add the marker to the map\n", "m.add(marker)\n", "\n", - "control = ipyleaflet.LayersControl(position='topright')\n", + "control = ipyleaflet.LayersControl(position=\"topright\")\n", "m.add(control)\n", "m" ] @@ -451,9 +451,9 @@ "metadata": {}, "outputs": [], "source": [ - "series = gj.SeriesMap(height = 500)\n", + "series = gj.SeriesMap(height=500)\n", "series.add_rasters([\"elevation\", \"elevation_shade\", \"slope\"])\n", - "#series.add_vectors([\"streams\", \"streets\", \"viewpoints\"])\n", + "# series.add_vectors([\"streams\", \"streets\", \"viewpoints\"])\n", "series.d_vect(map=\"streets\")\n", "series.d_barscale()\n", "series.show() # Create Slider" diff --git a/doc/notebooks/parallelization_tutorial.ipynb b/doc/notebooks/parallelization_tutorial.ipynb index 35a49fa2766..2c5d902e9a4 100644 --- a/doc/notebooks/parallelization_tutorial.ipynb +++ b/doc/notebooks/parallelization_tutorial.ipynb @@ -139,6 +139,7 @@ "import time\n", "from grass.pygrass.modules.grid import GridModule\n", "import time\n", + "\n", "start = time.time()\n", "grid = GridModule(\n", " \"v.surf.idw\",\n", diff --git a/doc/notebooks/scripting_example.ipynb b/doc/notebooks/scripting_example.ipynb index 612904da115..f71ebb8f284 100644 --- a/doc/notebooks/scripting_example.ipynb +++ b/doc/notebooks/scripting_example.ipynb @@ -74,7 +74,9 @@ "outputs": [], "source": [ "gs.parse_command(\"g.region\", raster=\"lakes\", flags=\"pg\")\n", - "gs.run_command(\"r.buffer\", input=\"lakes\", output=\"lakes_buff\", distances=[60, 120, 240, 500])\n", + "gs.run_command(\n", + " \"r.buffer\", input=\"lakes\", output=\"lakes_buff\", distances=[60, 120, 240, 500]\n", + ")\n", "gs.run_command(\"d.erase\")\n", "gs.run_command(\"d.rast\", map=\"lakes_buff\")\n", "gs.run_command(\"d.legend\", raster=\"lakes_buff\", range=(2, 5), at=(80, 100, 2, 10))\n", @@ -102,8 +104,12 @@ "gs.parse_command(\"g.region\", vector=\"boundary_state\", flags=\"pg\")\n", "gs.run_command(\"d.erase\") # erase the display before drawing again\n", "!rm -f $GRASS_LEGEND_FILE # and remove the legend file\n", - "gs.run_command(\"d.vect\", map=\"boundary_state\", fill_color=\"#5A91ED\", legend_label=\"State boundary\")\n", - "gs.run_command(\"d.vect\", map=\"buffer\", fill_color=\"#F8766D\", legend_label=\"Inner portion\")\n", + "gs.run_command(\n", + " \"d.vect\", map=\"boundary_state\", fill_color=\"#5A91ED\", legend_label=\"State boundary\"\n", + ")\n", + "gs.run_command(\n", + " \"d.vect\", map=\"buffer\", fill_color=\"#F8766D\", legend_label=\"Inner portion\"\n", + ")\n", "gs.run_command(\"d.legend.vect\", at=(10, 35))\n", "Image(filename=\"map.png\")" ] diff --git a/doc/notebooks/solar_potential.ipynb b/doc/notebooks/solar_potential.ipynb index cb3fd985910..98253ad6450 100644 --- a/doc/notebooks/solar_potential.ipynb +++ b/doc/notebooks/solar_potential.ipynb @@ -93,7 +93,18 @@ "metadata": {}, "outputs": [], "source": [ - "gs.run_command(\"r.sunmask\", elevation=\"elevation\", year=\"2001\", month=\"12\", day=\"22\", hour=\"16\", minute=\"15\", sec=\"0\", timezone=\"-5\", flags=\"s\")" + "gs.run_command(\n", + " \"r.sunmask\",\n", + " elevation=\"elevation\",\n", + " year=\"2001\",\n", + " month=\"12\",\n", + " day=\"22\",\n", + " hour=\"16\",\n", + " minute=\"15\",\n", + " sec=\"0\",\n", + " timezone=\"-5\",\n", + " flags=\"s\",\n", + ")" ] }, { @@ -111,7 +122,15 @@ "metadata": {}, "outputs": [], "source": [ - "gs.run_command(\"r.sun\", elevation=\"elevation\", aspect=\"aspect\", slope=\"slope\", incidout=\"incident\", day=\"356\", time=\"16.25\")\n", + "gs.run_command(\n", + " \"r.sun\",\n", + " elevation=\"elevation\",\n", + " aspect=\"aspect\",\n", + " slope=\"slope\",\n", + " incidout=\"incident\",\n", + " day=\"356\",\n", + " time=\"16.25\",\n", + ")\n", "gs.parse_command(\"r.info\", map=\"incident\", flags=\"g\")\n", "gs.run_command(\"r.colors\", map=\"incident\", co=\"bcyr\", flags=\"e\")" ] @@ -181,10 +200,26 @@ "metadata": {}, "outputs": [], "source": [ - "gs.run_command(\"r.sun\", elevation=\"elevation\", aspect=\"aspect\", slope=\"slope\", day=\"356\", glob_rad=\"winter\", insol_time=\"its356\")\n", + "gs.run_command(\n", + " \"r.sun\",\n", + " elevation=\"elevation\",\n", + " aspect=\"aspect\",\n", + " slope=\"slope\",\n", + " day=\"356\",\n", + " glob_rad=\"winter\",\n", + " insol_time=\"its356\",\n", + ")\n", "gs.run_command(\"r.colors\", map=\"winter\", co=\"gyr\", flags=\"e\")\n", "\n", - "gs.run_command(\"r.sun\", elevation=\"elevation\", aspect=\"aspect\", slope=\"slope\", day=\"172\", glob_rad=\"summer\", insol_time=\"its172\")\n", + "gs.run_command(\n", + " \"r.sun\",\n", + " elevation=\"elevation\",\n", + " aspect=\"aspect\",\n", + " slope=\"slope\",\n", + " day=\"172\",\n", + " glob_rad=\"summer\",\n", + " insol_time=\"its172\",\n", + ")\n", "gs.run_command(\"r.colors\", map=\"summer\", co=\"gyr\", flags=\"e\")" ] }, diff --git a/doc/notebooks/temporal.ipynb b/doc/notebooks/temporal.ipynb index 9a4433dc7fa..07e030a372c 100644 --- a/doc/notebooks/temporal.ipynb +++ b/doc/notebooks/temporal.ipynb @@ -32,7 +32,9 @@ "!curl http://fatra.cnr.ncsu.edu/temporal-grass-workshop/NC_spm_temporal_workshop.zip -o ../../data/NC_spm_temporal_workshop.zip\n", "\n", "# Unpack zip to grassdata\n", - "shutil.unpack_archive(\"../../data/NC_spm_temporal_workshop.zip\", \"../../data/grassdata\", \"zip\")" + "shutil.unpack_archive(\n", + " \"../../data/NC_spm_temporal_workshop.zip\", \"../../data/grassdata\", \"zip\"\n", + ")" ] }, { @@ -219,7 +221,7 @@ "source": [ "precip_map = gj.TimeSeriesMap(use_region=True)\n", "precip_map.add_raster_series(\"precip_sum_2010\")\n", - "precip_map.d_legend(color=\"black\", at=(10,40,2,6)) #Add legend\n", + "precip_map.d_legend(color=\"black\", at=(10, 40, 2, 6)) # Add legend\n", "precip_map.d_vect(map=\"boundary_county\", fill_color=\"none\")\n", "precip_map.d_barscale()\n", "precip_map.show()" @@ -240,7 +242,11 @@ "source": [ "from IPython.display import Image\n", "\n", - "Image(precip_map.save(\"image.gif\", duration=500, label=True, text_size=16, text_color=\"gray\"))" + "Image(\n", + " precip_map.save(\n", + " \"image.gif\", duration=500, label=True, text_size=16, text_color=\"gray\"\n", + " )\n", + ")" ] }, { diff --git a/doc/notebooks/viewshed_analysis.ipynb b/doc/notebooks/viewshed_analysis.ipynb index 263931ba25c..a4f0b61744a 100644 --- a/doc/notebooks/viewshed_analysis.ipynb +++ b/doc/notebooks/viewshed_analysis.ipynb @@ -65,8 +65,17 @@ "outputs": [], "source": [ "gs.parse_command(\"g.region\", raster=\"elevation\", flags=\"apg\")\n", - "gs.write_command(\"v.in.ascii\", input=\"-\", stdin=\"%s|%s\" % (642212, 224767), output=\"viewpoints\")\n", - "gs.run_command(\"r.viewshed\", input=\"elevation\", output=\"tower_los\", coordinates=\"642212,224767\", observer_elevation=\"165\", max_distance=\"10000\")" + "gs.write_command(\n", + " \"v.in.ascii\", input=\"-\", stdin=\"%s|%s\" % (642212, 224767), output=\"viewpoints\"\n", + ")\n", + "gs.run_command(\n", + " \"r.viewshed\",\n", + " input=\"elevation\",\n", + " output=\"tower_los\",\n", + " coordinates=\"642212,224767\",\n", + " observer_elevation=\"165\",\n", + " max_distance=\"10000\",\n", + ")" ] }, { diff --git a/general/g.mapsets/tests/conftest.py b/general/g.mapsets/tests/conftest.py index ca58228607c..ae4f1c106f9 100644 --- a/general/g.mapsets/tests/conftest.py +++ b/general/g.mapsets/tests/conftest.py @@ -5,7 +5,6 @@ Fixture for ReprojectionRenderer test with simple GRASS location, raster, vector. """ - from types import SimpleNamespace import grass.script as gs diff --git a/general/g.region/testsuite/test_g_region.py b/general/g.region/testsuite/test_g_region.py index b2f9d8aa83e..7362c062f1d 100644 --- a/general/g.region/testsuite/test_g_region.py +++ b/general/g.region/testsuite/test_g_region.py @@ -2,6 +2,7 @@ @author Anna Petrasova """ + from grass.gunittest.case import TestCase from grass.gunittest.gmodules import call_module import grass.script as gs diff --git a/gui/wxpython/animation/controller.py b/gui/wxpython/animation/controller.py index d6488d53263..ed03f7dadb5 100644 --- a/gui/wxpython/animation/controller.py +++ b/gui/wxpython/animation/controller.py @@ -13,6 +13,7 @@ @author Anna Petrasova """ + import os import wx diff --git a/gui/wxpython/animation/data.py b/gui/wxpython/animation/data.py index d19c2d21054..5c2cdf35ef1 100644 --- a/gui/wxpython/animation/data.py +++ b/gui/wxpython/animation/data.py @@ -15,6 +15,7 @@ @author Anna Petrasova """ + import os import copy diff --git a/gui/wxpython/animation/frame.py b/gui/wxpython/animation/frame.py index 38f07866264..e5bbd389d4c 100644 --- a/gui/wxpython/animation/frame.py +++ b/gui/wxpython/animation/frame.py @@ -17,6 +17,7 @@ @author Anna Petrasova """ + import os import wx import wx.aui diff --git a/gui/wxpython/animation/provider.py b/gui/wxpython/animation/provider.py index 10d83ec02f5..978c18e90cb 100644 --- a/gui/wxpython/animation/provider.py +++ b/gui/wxpython/animation/provider.py @@ -19,6 +19,7 @@ @author Anna Petrasova """ + import os import sys import wx @@ -427,9 +428,9 @@ def Render(self, cmdList, regions, regionFor3D, bgcolor, force, nprocs): for i in range(len(cmd_list)): proc_list[i].join() filename = queue_list[i].get() - self._mapFilesPool[ - HashCmd(cmd_list[i][0], cmd_list[i][1]) - ] = filename + self._mapFilesPool[HashCmd(cmd_list[i][0], cmd_list[i][1])] = ( + filename + ) self._mapFilesPool.SetSize( HashCmd(cmd_list[i][0], cmd_list[i][1]), (self.imageWidth, self.imageHeight), @@ -540,15 +541,17 @@ def Compose(self, cmdLists, regions, opacityList, bgcolor, force, nprocs): proc_list[i].join() filename = queue_list[i].get() if filename is None: - self._bitmapPool[ - HashCmds(cmd_lists[i][0], cmd_lists[i][1]) - ] = createNoDataBitmap( - self.imageWidth, self.imageHeight, text="Failed to render" + self._bitmapPool[HashCmds(cmd_lists[i][0], cmd_lists[i][1])] = ( + createNoDataBitmap( + self.imageWidth, + self.imageHeight, + text="Failed to render", + ) ) else: - self._bitmapPool[ - HashCmds(cmd_lists[i][0], cmd_lists[i][1]) - ] = BitmapFromImage(wx.Image(filename)) + self._bitmapPool[HashCmds(cmd_lists[i][0], cmd_lists[i][1])] = ( + BitmapFromImage(wx.Image(filename)) + ) os.remove(filename) proc_count = 0 proc_list = [] diff --git a/gui/wxpython/animation/temporal_manager.py b/gui/wxpython/animation/temporal_manager.py index 4fc31f75d26..a111edc81cb 100644 --- a/gui/wxpython/animation/temporal_manager.py +++ b/gui/wxpython/animation/temporal_manager.py @@ -221,9 +221,11 @@ def GetLabelsAndMaps(self): timestamps = [ ( datetime.datetime.strftime(st, formatString), - datetime.datetime.strftime(end, formatString) - if end is not None - else None, + ( + datetime.datetime.strftime(end, formatString) + if end is not None + else None + ), unit, ) for (st, end, unit) in timestamps diff --git a/gui/wxpython/animation/toolbars.py b/gui/wxpython/animation/toolbars.py index 0fc21c70366..1ac3c2efedb 100644 --- a/gui/wxpython/animation/toolbars.py +++ b/gui/wxpython/animation/toolbars.py @@ -17,6 +17,7 @@ @author Anna Petrasova """ + import wx from gui_core.toolbars import BaseToolbar, BaseIcons from icons.icon import MetaIcon diff --git a/gui/wxpython/animation/utils.py b/gui/wxpython/animation/utils.py index b6c0d27abac..9be0fe78c17 100644 --- a/gui/wxpython/animation/utils.py +++ b/gui/wxpython/animation/utils.py @@ -17,6 +17,7 @@ @author Anna Perasova """ + import os import wx import hashlib diff --git a/gui/wxpython/core/treemodel.py b/gui/wxpython/core/treemodel.py index 1c1fc2deee9..46f255021e9 100644 --- a/gui/wxpython/core/treemodel.py +++ b/gui/wxpython/core/treemodel.py @@ -15,6 +15,7 @@ @author Anna Petrasova """ + import copy from grass.script.utils import naturally_sort diff --git a/gui/wxpython/core/ws.py b/gui/wxpython/core/ws.py index 32dec87a05d..fc88772ff36 100644 --- a/gui/wxpython/core/ws.py +++ b/gui/wxpython/core/ws.py @@ -16,6 +16,7 @@ @author Stepan Turek (mentor: Martin Landa) """ + import sys import copy import time diff --git a/gui/wxpython/datacatalog/dialogs.py b/gui/wxpython/datacatalog/dialogs.py index 948238c7146..5e463e83543 100644 --- a/gui/wxpython/datacatalog/dialogs.py +++ b/gui/wxpython/datacatalog/dialogs.py @@ -14,7 +14,6 @@ @author Anna Petrasova """ - import wx from gui_core.widgets import FloatValidator, IntegerValidator from core.giface import Notification diff --git a/gui/wxpython/datacatalog/tree.py b/gui/wxpython/datacatalog/tree.py index 02d68f938a1..8821aeb61d4 100644 --- a/gui/wxpython/datacatalog/tree.py +++ b/gui/wxpython/datacatalog/tree.py @@ -18,6 +18,7 @@ @author Anna Petrasova (kratochanna gmail com) @author Linda Kladivova (l.kladivova@seznam.cz) """ + import os import re import copy diff --git a/gui/wxpython/gcp/statusbar.py b/gui/wxpython/gcp/statusbar.py index 1d10ad0b9b4..1424f7f4846 100644 --- a/gui/wxpython/gcp/statusbar.py +++ b/gui/wxpython/gcp/statusbar.py @@ -16,7 +16,6 @@ @author Anna Kratochvilova (statusbar refactoring) """ - import wx from core.gcmd import GMessage diff --git a/gui/wxpython/gui_core/menu.py b/gui/wxpython/gui_core/menu.py index 55ba0d40d48..3c1376cea0d 100644 --- a/gui/wxpython/gui_core/menu.py +++ b/gui/wxpython/gui_core/menu.py @@ -22,6 +22,7 @@ @author Vaclav Petras (menu customization) @author Tomas Zigo RecentFilesMenu """ + import re import os import wx diff --git a/gui/wxpython/gui_core/preferences.py b/gui/wxpython/gui_core/preferences.py index 257fafc4dca..85915c9567f 100644 --- a/gui/wxpython/gui_core/preferences.py +++ b/gui/wxpython/gui_core/preferences.py @@ -371,9 +371,9 @@ def _createGeneralPage(self, notebook): group="manager", key="copySelectedTextToClipboard", subkey="enabled" ) ) - self.winId[ - "manager:copySelectedTextToClipboard:enabled" - ] = copySelectedTextToClipboard.GetId() + self.winId["manager:copySelectedTextToClipboard:enabled"] = ( + copySelectedTextToClipboard.GetId() + ) gridSizer.Add(copySelectedTextToClipboard, pos=(row, 0), span=(1, 2)) @@ -1423,9 +1423,9 @@ def _createLayersPage(self, notebook): subkey=["transparent", "enabled"], ) ) - self.winId[ - "vectorLayer:featureColor:transparent:enabled" - ] = transpFeature.GetId() + self.winId["vectorLayer:featureColor:transparent:enabled"] = ( + transpFeature.GetId() + ) gridSizer.Add(transpFeature, pos=(row, col + 1), flag=wx.ALIGN_CENTER_VERTICAL) # area fill color diff --git a/gui/wxpython/gui_core/pystc.py b/gui/wxpython/gui_core/pystc.py index b11bf0f8418..bf268f88f33 100644 --- a/gui/wxpython/gui_core/pystc.py +++ b/gui/wxpython/gui_core/pystc.py @@ -15,7 +15,6 @@ @author Anna Petrasova (dark theme) """ - import keyword import wx diff --git a/gui/wxpython/gui_core/query.py b/gui/wxpython/gui_core/query.py index 638a64fa948..3a250af4d42 100644 --- a/gui/wxpython/gui_core/query.py +++ b/gui/wxpython/gui_core/query.py @@ -13,6 +13,7 @@ @author Anna Kratochvilova """ + import wx from gui_core.treeview import TreeListView diff --git a/gui/wxpython/iclass/dialogs.py b/gui/wxpython/iclass/dialogs.py index fb799e27057..868928efc89 100644 --- a/gui/wxpython/iclass/dialogs.py +++ b/gui/wxpython/iclass/dialogs.py @@ -19,6 +19,7 @@ @author Vaclav Petras @author Anna Kratochvilova """ + import os import wx diff --git a/gui/wxpython/icons/grass_icons.py b/gui/wxpython/icons/grass_icons.py index 2c13429d9ec..e4cd9b55ed7 100644 --- a/gui/wxpython/icons/grass_icons.py +++ b/gui/wxpython/icons/grass_icons.py @@ -3,6 +3,7 @@ http://robert.szczepanek.pl/icons.php https://svn.osgeo.org/osgeo/graphics/toolbar-icons/24x24/ """ + __author__ = "Robert Szczepanek" import os diff --git a/gui/wxpython/image2target/ii2t_statusbar.py b/gui/wxpython/image2target/ii2t_statusbar.py index 1d10ad0b9b4..1424f7f4846 100644 --- a/gui/wxpython/image2target/ii2t_statusbar.py +++ b/gui/wxpython/image2target/ii2t_statusbar.py @@ -16,7 +16,6 @@ @author Anna Kratochvilova (statusbar refactoring) """ - import wx from core.gcmd import GMessage diff --git a/gui/wxpython/iscatt/controllers.py b/gui/wxpython/iscatt/controllers.py index d3602d9124f..c526a4bf28d 100644 --- a/gui/wxpython/iscatt/controllers.py +++ b/gui/wxpython/iscatt/controllers.py @@ -19,6 +19,7 @@ @author Stepan Turek (mentor: Martin Landa) """ + from copy import deepcopy import wx diff --git a/gui/wxpython/iscatt/frame.py b/gui/wxpython/iscatt/frame.py index 242731ef182..9ff5a6ceac6 100644 --- a/gui/wxpython/iscatt/frame.py +++ b/gui/wxpython/iscatt/frame.py @@ -18,7 +18,6 @@ @author Stepan Turek (mentor: Martin Landa) """ - import os import wx diff --git a/gui/wxpython/iscatt/iscatt_core.py b/gui/wxpython/iscatt/iscatt_core.py index d97cdb84a56..1c5b2887edb 100644 --- a/gui/wxpython/iscatt/iscatt_core.py +++ b/gui/wxpython/iscatt/iscatt_core.py @@ -17,6 +17,7 @@ @author Stepan Turek (mentor: Martin Landa) """ + import os import numpy as np diff --git a/gui/wxpython/iscatt/plots.py b/gui/wxpython/iscatt/plots.py index be036ffd7b9..661da107754 100644 --- a/gui/wxpython/iscatt/plots.py +++ b/gui/wxpython/iscatt/plots.py @@ -15,6 +15,7 @@ @author Stepan Turek (mentor: Martin Landa) """ + import wx import numpy as np from math import ceil diff --git a/gui/wxpython/iscatt/toolbars.py b/gui/wxpython/iscatt/toolbars.py index 47d799e1961..6c5ab3947d6 100644 --- a/gui/wxpython/iscatt/toolbars.py +++ b/gui/wxpython/iscatt/toolbars.py @@ -13,6 +13,7 @@ @author Stepan Turek (mentor: Martin Landa) """ + import wx from icons.icon import MetaIcon diff --git a/gui/wxpython/location_wizard/dialogs.py b/gui/wxpython/location_wizard/dialogs.py index aaa0b4f1112..236913c211b 100644 --- a/gui/wxpython/location_wizard/dialogs.py +++ b/gui/wxpython/location_wizard/dialogs.py @@ -17,6 +17,7 @@ @author Jachym Cepicky @author Martin Landa """ + import os import wx diff --git a/gui/wxpython/location_wizard/wizard.py b/gui/wxpython/location_wizard/wizard.py index 4127d5047d4..4f3a2924847 100644 --- a/gui/wxpython/location_wizard/wizard.py +++ b/gui/wxpython/location_wizard/wizard.py @@ -33,6 +33,7 @@ @author Martin Landa @author Hamish Bowman (planetary ellipsoids) """ + import os import locale import functools diff --git a/gui/wxpython/mapwin/decorations.py b/gui/wxpython/mapwin/decorations.py index 5ead9c5f0e7..2eb5abe6075 100644 --- a/gui/wxpython/mapwin/decorations.py +++ b/gui/wxpython/mapwin/decorations.py @@ -32,7 +32,6 @@ class OverlayController: - """Base class for decorations (barscale, legend) controller.""" def __init__(self, renderer, giface): diff --git a/gui/wxpython/mapwin/graphics.py b/gui/wxpython/mapwin/graphics.py index 1522cf9f4dd..0bc94bae6d2 100644 --- a/gui/wxpython/mapwin/graphics.py +++ b/gui/wxpython/mapwin/graphics.py @@ -15,7 +15,6 @@ @author Stepan Turek (handlers support, GraphicsSet) """ - from copy import copy import wx diff --git a/gui/wxpython/nviz/mapwindow.py b/gui/wxpython/nviz/mapwindow.py index 1c291e1068b..fa9f51207da 100644 --- a/gui/wxpython/nviz/mapwindow.py +++ b/gui/wxpython/nviz/mapwindow.py @@ -2066,18 +2066,18 @@ def UpdateVolumeProperties(self, id, data, isosurfId=None): if ( data["draw"]["shading"]["isosurface"]["value"] < 0 ): # need to calculate - mode = data["draw"]["shading"]["isosurface"][ - "value" - ] = self.nvizDefault.GetDrawMode( - shade=data["draw"]["shading"]["isosurface"], string=False + mode = data["draw"]["shading"]["isosurface"]["value"] = ( + self.nvizDefault.GetDrawMode( + shade=data["draw"]["shading"]["isosurface"], string=False + ) ) self._display.SetIsosurfaceMode(id, mode) else: if data["draw"]["shading"]["slice"]["value"] < 0: # need to calculate - mode = data["draw"]["shading"]["slice"][ - "value" - ] = self.nvizDefault.GetDrawMode( - shade=data["draw"]["shading"]["slice"], string=False + mode = data["draw"]["shading"]["slice"]["value"] = ( + self.nvizDefault.GetDrawMode( + shade=data["draw"]["shading"]["slice"], string=False + ) ) self._display.SetSliceMode(id, mode) data["draw"]["shading"].pop("update") @@ -2504,17 +2504,7 @@ def NvizCmdCommand(self): # vlines # if vectors: - cmdLines = ( - cmdLWidth - ) = ( - cmdLHeight - ) = ( - cmdLColor - ) = ( - cmdLMode - ) = ( - cmdLPos - ) = ( + cmdLines = cmdLWidth = cmdLHeight = cmdLColor = cmdLMode = cmdLPos = ( cmdPoints ) = cmdPWidth = cmdPSize = cmdPColor = cmdPMarker = cmdPPos = cmdPLayer = "" markers = [ diff --git a/gui/wxpython/photo2image/ip2i_statusbar.py b/gui/wxpython/photo2image/ip2i_statusbar.py index c1fcf9a9907..3415906aeee 100644 --- a/gui/wxpython/photo2image/ip2i_statusbar.py +++ b/gui/wxpython/photo2image/ip2i_statusbar.py @@ -16,7 +16,6 @@ @author Anna Kratochvilova (statusbar refactoring) """ - import wx from core.gcmd import GMessage diff --git a/gui/wxpython/psmap/dialogs.py b/gui/wxpython/psmap/dialogs.py index 1e0a7851409..88c2f5abc98 100644 --- a/gui/wxpython/psmap/dialogs.py +++ b/gui/wxpython/psmap/dialogs.py @@ -3212,9 +3212,9 @@ def update(self): if self.colorColRadio.GetValue(): # this color is taken in case of no record in rgb column self.vPropertiesDict["fcolor"] = "none" - self.vPropertiesDict[ - "rgbcolumn" - ] = self.colorColChoice.GetStringSelection() + self.vPropertiesDict["rgbcolumn"] = ( + self.colorColChoice.GetStringSelection() + ) else: self.vPropertiesDict["fcolor"] = "none" @@ -3238,9 +3238,9 @@ def update(self): if self.colorColRadio.GetValue(): # this color is taken in case of no record in rgb column self.vPropertiesDict["color"] = "none" - self.vPropertiesDict[ - "rgbcolumn" - ] = self.colorColChoice.GetStringSelection() + self.vPropertiesDict["rgbcolumn"] = ( + self.colorColChoice.GetStringSelection() + ) # # size and style # @@ -3258,9 +3258,9 @@ def update(self): self.vPropertiesDict["sizecolumn"] = None self.vPropertiesDict["scale"] = None else: - self.vPropertiesDict[ - "sizecolumn" - ] = self.sizeColChoice.GetStringSelection() + self.vPropertiesDict["sizecolumn"] = ( + self.sizeColChoice.GetStringSelection() + ) self.vPropertiesDict["scale"] = self.scaleSpin.GetValue() self.vPropertiesDict["size"] = None @@ -3273,9 +3273,9 @@ def update(self): if self.rotateRadio.GetValue(): self.vPropertiesDict["rotate"] = self.rotateSpin.GetValue() else: - self.vPropertiesDict[ - "rotatecolumn" - ] = self.rotateColChoice.GetStringSelection() + self.vPropertiesDict["rotatecolumn"] = ( + self.rotateColChoice.GetStringSelection() + ) if self.type == "areas": # pattern diff --git a/gui/wxpython/psmap/frame.py b/gui/wxpython/psmap/frame.py index 85ccbae0067..88a4ad08dd5 100644 --- a/gui/wxpython/psmap/frame.py +++ b/gui/wxpython/psmap/frame.py @@ -2292,10 +2292,10 @@ def Zoom(self, zoomFactor, view): rot = float(self.instruction[id]["rotate"]) else: rot = 0 - self.instruction[id][ - "rect" - ] = bounds = self.parent.getModifiedTextBounds( - coords[0], coords[1], extent, rot + self.instruction[id]["rect"] = bounds = ( + self.parent.getModifiedTextBounds( + coords[0], coords[1], extent, rot + ) ) self.DrawRotText( pdc=self.pdcObj, diff --git a/gui/wxpython/psmap/utils.py b/gui/wxpython/psmap/utils.py index af68405446f..f7e4cea1ad3 100644 --- a/gui/wxpython/psmap/utils.py +++ b/gui/wxpython/psmap/utils.py @@ -15,6 +15,7 @@ @author Anna Kratochvilova """ + import wx from math import ceil, floor, sin, cos, pi diff --git a/gui/wxpython/rdigit/controller.py b/gui/wxpython/rdigit/controller.py index 26e9f455e68..2e98ca32ccc 100644 --- a/gui/wxpython/rdigit/controller.py +++ b/gui/wxpython/rdigit/controller.py @@ -13,6 +13,7 @@ @author Anna Petrasova """ + import os import tempfile import wx diff --git a/gui/wxpython/rlisetup/functions.py b/gui/wxpython/rlisetup/functions.py index d77962a97c1..2b9433ea4d6 100644 --- a/gui/wxpython/rlisetup/functions.py +++ b/gui/wxpython/rlisetup/functions.py @@ -3,6 +3,7 @@ @author: lucadelu """ + import wx import os import sys diff --git a/gui/wxpython/startup/guiutils.py b/gui/wxpython/startup/guiutils.py index ca04e52aefc..d94da9f9b16 100644 --- a/gui/wxpython/startup/guiutils.py +++ b/gui/wxpython/startup/guiutils.py @@ -14,7 +14,6 @@ This is for code which depend on something from GUI (wx or wxGUI). """ - import os import wx diff --git a/gui/wxpython/vdigit/toolbars.py b/gui/wxpython/vdigit/toolbars.py index 306732e79b4..fb461118d2a 100644 --- a/gui/wxpython/vdigit/toolbars.py +++ b/gui/wxpython/vdigit/toolbars.py @@ -14,6 +14,7 @@ @author Martin Landa @author Stepan Turek (handlers support) """ + import wx from grass import script as grass diff --git a/gui/wxpython/vdigit/wxdigit.py b/gui/wxpython/vdigit/wxdigit.py index 9cf6005a077..0c36100e561 100644 --- a/gui/wxpython/vdigit/wxdigit.py +++ b/gui/wxpython/vdigit/wxdigit.py @@ -26,7 +26,6 @@ @author Martin Landa """ - import grass.script.core as grass from grass.pydispatch.signal import Signal diff --git a/gui/wxpython/vdigit/wxdisplay.py b/gui/wxpython/vdigit/wxdisplay.py index 21f86f3718d..988afc481ac 100644 --- a/gui/wxpython/vdigit/wxdisplay.py +++ b/gui/wxpython/vdigit/wxdisplay.py @@ -17,7 +17,6 @@ @author Martin Landa """ - import locale import os diff --git a/gui/wxpython/vnet/toolbars.py b/gui/wxpython/vnet/toolbars.py index bb0a1aacdd5..5f80e50cd9d 100644 --- a/gui/wxpython/vnet/toolbars.py +++ b/gui/wxpython/vnet/toolbars.py @@ -85,7 +85,7 @@ def _toolbarData(self): icons["pointDelete"], self.OnDeletePoint, ), - (None,) # , + (None,), # , # ('isec_turn_edit', icons['isec_turn_edit'], # self.dialog.OnDefIsecTurnCosts, # wx.ITEM_CHECK), diff --git a/gui/wxpython/vnet/vnet_data.py b/gui/wxpython/vnet/vnet_data.py index 946e31975e8..528efa0a6c2 100644 --- a/gui/wxpython/vnet/vnet_data.py +++ b/gui/wxpython/vnet/vnet_data.py @@ -22,6 +22,7 @@ @author Lukas Bocan (turn costs support) @author Eliska Kyzlikova (turn costs support) """ + import os import math from copy import deepcopy diff --git a/gui/wxpython/wxplot/profile.py b/gui/wxpython/wxplot/profile.py index 591608767d7..1b55da68919 100644 --- a/gui/wxpython/wxplot/profile.py +++ b/gui/wxpython/wxplot/profile.py @@ -234,9 +234,11 @@ def SetupProfile(self): # transect self.seglist.append( ( - segment_geodesic_cum_dist - if self._is_lat_lon_proj and haveCtypes - else cumdist, + ( + segment_geodesic_cum_dist + if self._is_lat_lon_proj and haveCtypes + else cumdist + ), val, ) ) diff --git a/imagery/i.pca/testsuite/test_pca.py b/imagery/i.pca/testsuite/test_pca.py index 9da7991f876..8e9df84f2eb 100644 --- a/imagery/i.pca/testsuite/test_pca.py +++ b/imagery/i.pca/testsuite/test_pca.py @@ -8,6 +8,7 @@ License (>=v2). Read the file COPYING that comes with GRASS for details. """ + from grass.gunittest.case import TestCase diff --git a/imagery/i.segment/testsuite/test_isegment.py b/imagery/i.segment/testsuite/test_isegment.py index 09046f980af..66d24d41661 100644 --- a/imagery/i.segment/testsuite/test_isegment.py +++ b/imagery/i.segment/testsuite/test_isegment.py @@ -8,6 +8,7 @@ License (>=v2). Read the file COPYING that comes with GRASS for details. """ + from grass.gunittest.case import TestCase diff --git a/imagery/i.signatures/testsuite/test_i_signatures.py b/imagery/i.signatures/testsuite/test_i_signatures.py index 34f38774bc0..651d510ed03 100644 --- a/imagery/i.signatures/testsuite/test_i_signatures.py +++ b/imagery/i.signatures/testsuite/test_i_signatures.py @@ -8,6 +8,7 @@ Read the file COPYING that comes with GRASS for details """ + import os import shutil import json diff --git a/imagery/i.svm.predict/testsuite/test_i_svm_predict.py b/imagery/i.svm.predict/testsuite/test_i_svm_predict.py index 706af4f4fa2..3662124f45d 100644 --- a/imagery/i.svm.predict/testsuite/test_i_svm_predict.py +++ b/imagery/i.svm.predict/testsuite/test_i_svm_predict.py @@ -8,6 +8,7 @@ License (>=v2). Read the file COPYING that comes with GRASS for details. """ + import unittest import shutil diff --git a/imagery/i.svm.train/testsuite/test_i_svm_train.py b/imagery/i.svm.train/testsuite/test_i_svm_train.py index d895ffcd22f..f097405d98f 100644 --- a/imagery/i.svm.train/testsuite/test_i_svm_train.py +++ b/imagery/i.svm.train/testsuite/test_i_svm_train.py @@ -8,6 +8,7 @@ License (>=v2). Read the file COPYING that comes with GRASS for details. """ + import os import unittest import ctypes diff --git a/imagery/i.vi/testsuite/test_vi.py b/imagery/i.vi/testsuite/test_vi.py index a0da8245a5e..0c383417257 100644 --- a/imagery/i.vi/testsuite/test_vi.py +++ b/imagery/i.vi/testsuite/test_vi.py @@ -8,6 +8,7 @@ License (>=v2). Read the file COPYING that comes with GRASS for details. """ + from grass.gunittest.case import TestCase diff --git a/lib/gis/testsuite/gis_lib_env_test.py b/lib/gis/testsuite/gis_lib_env_test.py index 91382f552c0..fafc00a37ed 100644 --- a/lib/gis/testsuite/gis_lib_env_test.py +++ b/lib/gis/testsuite/gis_lib_env_test.py @@ -2,6 +2,7 @@ @author Soeren Gebbert """ + from grass.gunittest.case import TestCase import grass.lib.gis as libgis diff --git a/lib/imagery/testsuite/test_imagery_find.py b/lib/imagery/testsuite/test_imagery_find.py index a943e2d3520..72e99bc2776 100644 --- a/lib/imagery/testsuite/test_imagery_find.py +++ b/lib/imagery/testsuite/test_imagery_find.py @@ -8,6 +8,7 @@ Read the file COPYING that comes with GRASS for details """ + import os import shutil diff --git a/lib/imagery/testsuite/test_imagery_sigfile.py b/lib/imagery/testsuite/test_imagery_sigfile.py index c8bc90a4f95..104cd5a59b4 100644 --- a/lib/imagery/testsuite/test_imagery_sigfile.py +++ b/lib/imagery/testsuite/test_imagery_sigfile.py @@ -8,6 +8,7 @@ Read the file COPYING that comes with GRASS for details """ + import os import stat import ctypes @@ -383,9 +384,9 @@ def test_symmetric_complete_difference(self): self.assertEqual(ref_err, "The_Doors") # Clean up memory to help track memory leaks when run by valgrind - S.semantic_labels[ - 0 - ] = None # C should not call free() on memory allocated by python + S.semantic_labels[0] = ( + None # C should not call free() on memory allocated by python + ) I_free_signatures(ctypes.byref(S)) I_free_group_ref(ctypes.byref(R)) if ret: diff --git a/lib/imagery/testsuite/test_imagery_signature_management.py b/lib/imagery/testsuite/test_imagery_signature_management.py index b2ec954a74e..21f052372e2 100644 --- a/lib/imagery/testsuite/test_imagery_signature_management.py +++ b/lib/imagery/testsuite/test_imagery_signature_management.py @@ -8,6 +8,7 @@ Read the file COPYING that comes with GRASS for details """ + import os import shutil import ctypes diff --git a/lib/imagery/testsuite/test_imagery_sigsetfile.py b/lib/imagery/testsuite/test_imagery_sigsetfile.py index 6e5a119c236..b8bcb566520 100644 --- a/lib/imagery/testsuite/test_imagery_sigsetfile.py +++ b/lib/imagery/testsuite/test_imagery_sigsetfile.py @@ -8,6 +8,7 @@ Read the file COPYING that comes with GRASS for details """ + import os import stat import ctypes diff --git a/lib/raster/testsuite/test_raster_metadata.py b/lib/raster/testsuite/test_raster_metadata.py index 7da2c0fe4cf..43bbfaeea99 100644 --- a/lib/raster/testsuite/test_raster_metadata.py +++ b/lib/raster/testsuite/test_raster_metadata.py @@ -8,6 +8,7 @@ Read the file COPYING that comes with GRASS for details """ + import random import string diff --git a/lib/raster3d/testsuite/raster3d_lib_test.py b/lib/raster3d/testsuite/raster3d_lib_test.py index 5ec919c94ba..a0020ab9ef1 100644 --- a/lib/raster3d/testsuite/raster3d_lib_test.py +++ b/lib/raster3d/testsuite/raster3d_lib_test.py @@ -2,6 +2,7 @@ @author Soeren Gebbert """ + from grass.gunittest.case import TestCase diff --git a/man/parser_standard_options.py b/man/parser_standard_options.py index 3454084f330..6a6d769ab5e 100644 --- a/man/parser_standard_options.py +++ b/man/parser_standard_options.py @@ -3,6 +3,7 @@ @author: pietro """ + import argparse import os import sys diff --git a/pyproject.toml b/pyproject.toml index e06ff451bd0..c99b85ab4dc 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,24 +1,11 @@ [tool.black] +required-version = '24' line-length = 88 -target-version = ['py37', 'py38', 'py39', 'py310'] -include = '\.pyi?$' -exclude = ''' +target-version = ['py38', 'py39', 'py310', 'py311', 'py312'] +# 'extend-exclude' excludes files or directories in addition to the defaults +extend-exclude = ''' ( - # exclude directories in the root of the project - /( - \.eggs - | \.git - | \.hg - | \.mypy_cache - | \.tox - | \.venv - | _build - | buck-out - | build - | bin\..* - | dist\..* - )/ - | python/libgrass_interface_generator/ + python/libgrass_interface_generator/ ) ''' diff --git a/python/grass/grassdb/create.py b/python/grass/grassdb/create.py index f7e7b509405..041b5ed28f8 100644 --- a/python/grass/grassdb/create.py +++ b/python/grass/grassdb/create.py @@ -9,7 +9,6 @@ .. sectionauthor:: Vaclav Petras """ - import os import shutil import getpass diff --git a/python/grass/grassdb/manage.py b/python/grass/grassdb/manage.py index c79df87ce07..0446263615e 100644 --- a/python/grass/grassdb/manage.py +++ b/python/grass/grassdb/manage.py @@ -9,7 +9,6 @@ .. sectionauthor:: Vaclav Petras """ - import os import shutil import sys diff --git a/python/grass/gunittest/multireport.py b/python/grass/gunittest/multireport.py index 54c1c915909..014d8296e4b 100644 --- a/python/grass/gunittest/multireport.py +++ b/python/grass/gunittest/multireport.py @@ -9,7 +9,6 @@ :authors: Vaclav Petras """ - import sys import os import argparse diff --git a/python/grass/gunittest/runner.py b/python/grass/gunittest/runner.py index 8879527a24c..891e1b65a5a 100644 --- a/python/grass/gunittest/runner.py +++ b/python/grass/gunittest/runner.py @@ -12,7 +12,6 @@ a template. It is not expected that something will left. """ - import sys import time diff --git a/python/grass/gunittest/testsuite/test_assertions.py b/python/grass/gunittest/testsuite/test_assertions.py index fb14e50bbd8..bf0f946d37d 100644 --- a/python/grass/gunittest/testsuite/test_assertions.py +++ b/python/grass/gunittest/testsuite/test_assertions.py @@ -2,7 +2,6 @@ Tests assertion methods. """ - import os import grass.script.core as gcore diff --git a/python/grass/gunittest/testsuite/test_checkers.py b/python/grass/gunittest/testsuite/test_checkers.py index 8d6571a8aa4..d35ffcb19d8 100644 --- a/python/grass/gunittest/testsuite/test_checkers.py +++ b/python/grass/gunittest/testsuite/test_checkers.py @@ -11,7 +11,6 @@ @author Vaclav Petras """ - from grass.script.utils import parse_key_val, try_remove from grass.gunittest.case import TestCase diff --git a/python/grass/imaging/operations.py b/python/grass/imaging/operations.py index d1837a485b0..8c60c4c599e 100644 --- a/python/grass/imaging/operations.py +++ b/python/grass/imaging/operations.py @@ -53,7 +53,6 @@ .. sectionauthor:: Vaclav Petras """ - # import similar to what is in visvis try: import PIL diff --git a/python/grass/jupyter/tests/seriesmap_test.py b/python/grass/jupyter/tests/seriesmap_test.py index 79f3b20dbda..e19faf5f663 100644 --- a/python/grass/jupyter/tests/seriesmap_test.py +++ b/python/grass/jupyter/tests/seriesmap_test.py @@ -1,6 +1,5 @@ """Test SeriesMap functions""" - from pathlib import Path import pytest diff --git a/python/grass/jupyter/tests/timeseriesmap_test.py b/python/grass/jupyter/tests/timeseriesmap_test.py index ed7e5c6e156..d75ec8372e4 100644 --- a/python/grass/jupyter/tests/timeseriesmap_test.py +++ b/python/grass/jupyter/tests/timeseriesmap_test.py @@ -1,6 +1,5 @@ """Test TimeSeriesMap functions""" - from pathlib import Path import pytest diff --git a/python/grass/pydispatch/dispatcher.py b/python/grass/pydispatch/dispatcher.py index a34706f8cf7..0915629fdd9 100644 --- a/python/grass/pydispatch/dispatcher.py +++ b/python/grass/pydispatch/dispatcher.py @@ -25,6 +25,7 @@ deletion, (considerably speeds up the cleanup process vs. the original code.) """ + import weakref from grass.pydispatch import saferef, robustapply, errors diff --git a/python/grass/pydispatch/robust.py b/python/grass/pydispatch/robust.py index f65471037d7..9923d3afc90 100644 --- a/python/grass/pydispatch/robust.py +++ b/python/grass/pydispatch/robust.py @@ -1,4 +1,5 @@ """Module implementing error-catching version of send (sendRobust)""" + from grass.pydispatch.dispatcher import Any, Anonymous, liveReceivers, getAllReceivers from grass.pydispatch.robustapply import robustApply diff --git a/python/grass/pydispatch/robustapply.py b/python/grass/pydispatch/robustapply.py index ac4211bbddf..1c10bc917c6 100644 --- a/python/grass/pydispatch/robustapply.py +++ b/python/grass/pydispatch/robustapply.py @@ -5,6 +5,7 @@ and subset the given arguments to match only those which are acceptable. """ + import sys if sys.hexversion >= 0x3000000: diff --git a/python/grass/pydispatch/signal.py b/python/grass/pydispatch/signal.py index edb962853da..1e968e99dca 100644 --- a/python/grass/pydispatch/signal.py +++ b/python/grass/pydispatch/signal.py @@ -4,7 +4,6 @@ @author Vaclav Petras """ - from grass.pydispatch import dispatcher diff --git a/python/grass/pygrass/gis/region.py b/python/grass/pygrass/gis/region.py index 02a273a6ac6..453c2c84f5f 100644 --- a/python/grass/pygrass/gis/region.py +++ b/python/grass/pygrass/gis/region.py @@ -3,6 +3,7 @@ @author: Pietro Zambelli """ + import ctypes import grass.lib.gis as libgis import grass.lib.raster as libraster diff --git a/python/grass/pygrass/messages/__init__.py b/python/grass/pygrass/messages/__init__.py index 60e8e43e31c..36356433381 100644 --- a/python/grass/pygrass/messages/__init__.py +++ b/python/grass/pygrass/messages/__init__.py @@ -13,6 +13,7 @@ @author Soeren Gebbert """ + import sys from multiprocessing import Process, Lock, Pipe diff --git a/python/grass/pygrass/modules/grid/patch.py b/python/grass/pygrass/modules/grid/patch.py index 3d7c5432e43..be555583591 100644 --- a/python/grass/pygrass/modules/grid/patch.py +++ b/python/grass/pygrass/modules/grid/patch.py @@ -3,6 +3,7 @@ @author: pietro """ + from grass.pygrass.gis.region import Region from grass.pygrass.raster import RasterRow from grass.pygrass.utils import coor2pixel diff --git a/python/grass/pygrass/modules/grid/split.py b/python/grass/pygrass/modules/grid/split.py index a32665f5fcc..5ff56a3e737 100644 --- a/python/grass/pygrass/modules/grid/split.py +++ b/python/grass/pygrass/modules/grid/split.py @@ -3,6 +3,7 @@ @author: pietro """ + from grass.pygrass.gis.region import Region from grass.pygrass.vector.basic import Bbox diff --git a/python/grass/pygrass/modules/interface/__init__.py b/python/grass/pygrass/modules/interface/__init__.py index 37546d463dd..a05211e21c3 100644 --- a/python/grass/pygrass/modules/interface/__init__.py +++ b/python/grass/pygrass/modules/interface/__init__.py @@ -3,6 +3,7 @@ @author: pietro """ + from grass.pygrass.modules.interface import flag from grass.pygrass.modules.interface import parameter from grass.pygrass.modules.interface import module diff --git a/python/grass/pygrass/modules/interface/env.py b/python/grass/pygrass/modules/interface/env.py index 98e5208ef5b..4fbef04dae3 100644 --- a/python/grass/pygrass/modules/interface/env.py +++ b/python/grass/pygrass/modules/interface/env.py @@ -3,6 +3,7 @@ @author: pietro """ + import os import sys diff --git a/python/grass/pygrass/modules/interface/parameter.py b/python/grass/pygrass/modules/interface/parameter.py index 7ab67c186ad..161640e638e 100644 --- a/python/grass/pygrass/modules/interface/parameter.py +++ b/python/grass/pygrass/modules/interface/parameter.py @@ -3,6 +3,7 @@ @author: pietro """ + import re from grass.pygrass.modules.interface.docstring import docstring_property @@ -249,9 +250,11 @@ def get_bash(self): if isinstance(self.rawvalue, (list, tuple)): value = sep.join( [ - sep.join([str(v) for v in val]) - if isinstance(val, tuple) - else str(val) + ( + sep.join([str(v) for v in val]) + if isinstance(val, tuple) + else str(val) + ) for val in self.rawvalue ] ) diff --git a/python/grass/pygrass/modules/interface/testsuite/test_flag.py b/python/grass/pygrass/modules/interface/testsuite/test_flag.py index 26b9ba531ff..909c6d00d55 100644 --- a/python/grass/pygrass/modules/interface/testsuite/test_flag.py +++ b/python/grass/pygrass/modules/interface/testsuite/test_flag.py @@ -3,6 +3,7 @@ @author: pietro """ + from grass.gunittest.case import TestCase from grass.gunittest.main import test diff --git a/python/grass/pygrass/modules/interface/testsuite/test_modules.py b/python/grass/pygrass/modules/interface/testsuite/test_modules.py index 10b4c3f2529..d95bf6177af 100644 --- a/python/grass/pygrass/modules/interface/testsuite/test_modules.py +++ b/python/grass/pygrass/modules/interface/testsuite/test_modules.py @@ -3,6 +3,7 @@ @author: pietro """ + from fnmatch import fnmatch from io import BytesIO diff --git a/python/grass/pygrass/modules/interface/testsuite/test_parameter.py b/python/grass/pygrass/modules/interface/testsuite/test_parameter.py index e3bf9921bfd..57f17cb3027 100644 --- a/python/grass/pygrass/modules/interface/testsuite/test_parameter.py +++ b/python/grass/pygrass/modules/interface/testsuite/test_parameter.py @@ -3,6 +3,7 @@ @author: pietro """ + from grass.gunittest.case import TestCase from grass.gunittest.main import test diff --git a/python/grass/pygrass/modules/interface/typedict.py b/python/grass/pygrass/modules/interface/typedict.py index f2ece769d6c..c8fdeb48a76 100644 --- a/python/grass/pygrass/modules/interface/typedict.py +++ b/python/grass/pygrass/modules/interface/typedict.py @@ -3,6 +3,7 @@ @author: pietro """ + from collections import OrderedDict from copy import deepcopy diff --git a/python/grass/pygrass/modules/testsuite/test_import_isolation.py b/python/grass/pygrass/modules/testsuite/test_import_isolation.py index d91ae1a830b..d1321a554d0 100644 --- a/python/grass/pygrass/modules/testsuite/test_import_isolation.py +++ b/python/grass/pygrass/modules/testsuite/test_import_isolation.py @@ -9,6 +9,7 @@ Created on Wed Jul 15 11:34:32 2015 """ + import sys import fnmatch diff --git a/python/grass/pygrass/raster/abstract.py b/python/grass/pygrass/raster/abstract.py index 76d638db7db..6969154b7fb 100644 --- a/python/grass/pygrass/raster/abstract.py +++ b/python/grass/pygrass/raster/abstract.py @@ -3,6 +3,7 @@ @author: pietro """ + import ctypes # diff --git a/python/grass/pygrass/raster/category.py b/python/grass/pygrass/raster/category.py index b7a1294d96c..b43a10ae48d 100644 --- a/python/grass/pygrass/raster/category.py +++ b/python/grass/pygrass/raster/category.py @@ -3,6 +3,7 @@ @author: pietro """ + import ctypes from operator import itemgetter diff --git a/python/grass/pygrass/raster/history.py b/python/grass/pygrass/raster/history.py index 6140a6197b2..5041c9e55d8 100644 --- a/python/grass/pygrass/raster/history.py +++ b/python/grass/pygrass/raster/history.py @@ -3,6 +3,7 @@ @author: pietro """ + import ctypes import grass.lib.raster as libraster import datetime diff --git a/python/grass/pygrass/raster/raster_type.py b/python/grass/pygrass/raster/raster_type.py index 0b8244fe551..aa54a6d6df6 100644 --- a/python/grass/pygrass/raster/raster_type.py +++ b/python/grass/pygrass/raster/raster_type.py @@ -3,6 +3,7 @@ @author: pietro """ + import grass.lib.raster as libraster import ctypes import numpy as np diff --git a/python/grass/pygrass/raster/rowio.py b/python/grass/pygrass/raster/rowio.py index 650419122c3..62c5683ef68 100644 --- a/python/grass/pygrass/raster/rowio.py +++ b/python/grass/pygrass/raster/rowio.py @@ -3,6 +3,7 @@ @author: pietro """ + import ctypes import grass.lib.rowio as librowio diff --git a/python/grass/pygrass/raster/segment.py b/python/grass/pygrass/raster/segment.py index 6e9c4c4c781..60966d0f846 100644 --- a/python/grass/pygrass/raster/segment.py +++ b/python/grass/pygrass/raster/segment.py @@ -3,6 +3,7 @@ @author: pietro """ + import ctypes import grass.lib.gis as libgis import grass.lib.raster as libraster diff --git a/python/grass/pygrass/raster/testsuite/test_numpy.py b/python/grass/pygrass/raster/testsuite/test_numpy.py index c773e628f96..a2a6e1cdd26 100644 --- a/python/grass/pygrass/raster/testsuite/test_numpy.py +++ b/python/grass/pygrass/raster/testsuite/test_numpy.py @@ -3,6 +3,7 @@ @author: lucadelu """ + from grass.gunittest.case import TestCase from grass.gunittest.main import test from numpy.random import random diff --git a/python/grass/pygrass/shell/conversion.py b/python/grass/pygrass/shell/conversion.py index 344dfd2811b..76802c08ce1 100644 --- a/python/grass/pygrass/shell/conversion.py +++ b/python/grass/pygrass/shell/conversion.py @@ -4,7 +4,6 @@ @author: pietro """ - dcont = """ {key} {value} diff --git a/python/grass/pygrass/vector/abstract.py b/python/grass/pygrass/vector/abstract.py index e1dda3a8d7d..bafbb006d6c 100644 --- a/python/grass/pygrass/vector/abstract.py +++ b/python/grass/pygrass/vector/abstract.py @@ -3,6 +3,7 @@ @author: pietro """ + import ctypes import datetime import grass.lib.vector as libvect diff --git a/python/grass/pygrass/vector/basic.py b/python/grass/pygrass/vector/basic.py index 8917629ca43..2b8c013b433 100644 --- a/python/grass/pygrass/vector/basic.py +++ b/python/grass/pygrass/vector/basic.py @@ -3,6 +3,7 @@ @author: pietro """ + import ctypes import grass.lib.vector as libvect from collections.abc import Iterable diff --git a/python/grass/pygrass/vector/find.py b/python/grass/pygrass/vector/find.py index ac56265447c..50599af5ab5 100644 --- a/python/grass/pygrass/vector/find.py +++ b/python/grass/pygrass/vector/find.py @@ -3,6 +3,7 @@ @author: pietro """ + import grass.lib.vector as libvect from grass.pygrass.errors import must_be_open diff --git a/python/grass/pygrass/vector/geometry.py b/python/grass/pygrass/vector/geometry.py index 81d9f3a8d78..855f374b47e 100644 --- a/python/grass/pygrass/vector/geometry.py +++ b/python/grass/pygrass/vector/geometry.py @@ -3,6 +3,7 @@ @author: pietro """ + import ctypes import re from collections import namedtuple diff --git a/python/grass/pygrass/vector/testsuite/test_filters.py b/python/grass/pygrass/vector/testsuite/test_filters.py index 6d3d7247f66..9252b134c02 100644 --- a/python/grass/pygrass/vector/testsuite/test_filters.py +++ b/python/grass/pygrass/vector/testsuite/test_filters.py @@ -3,6 +3,7 @@ @author: pietro """ + from grass.gunittest.case import TestCase from grass.gunittest.main import test diff --git a/python/grass/pygrass/vector/testsuite/test_geometry.py b/python/grass/pygrass/vector/testsuite/test_geometry.py index a81c7d4a96f..d4ad7431278 100644 --- a/python/grass/pygrass/vector/testsuite/test_geometry.py +++ b/python/grass/pygrass/vector/testsuite/test_geometry.py @@ -3,6 +3,7 @@ @author: pietro """ + import sys import unittest import numpy as np diff --git a/python/grass/pygrass/vector/testsuite/test_geometry_attrs.py b/python/grass/pygrass/vector/testsuite/test_geometry_attrs.py index a1b75e0e9a6..4c17ef03d4c 100644 --- a/python/grass/pygrass/vector/testsuite/test_geometry_attrs.py +++ b/python/grass/pygrass/vector/testsuite/test_geometry_attrs.py @@ -3,6 +3,7 @@ @author: pietro """ + import sys import unittest import numpy as np diff --git a/python/grass/pygrass/vector/testsuite/test_table.py b/python/grass/pygrass/vector/testsuite/test_table.py index d80be7beb04..d603817de98 100644 --- a/python/grass/pygrass/vector/testsuite/test_table.py +++ b/python/grass/pygrass/vector/testsuite/test_table.py @@ -3,6 +3,7 @@ @author: pietro """ + import os import sqlite3 import tempfile as tmp diff --git a/python/grass/pygrass/vector/testsuite/test_vector.py b/python/grass/pygrass/vector/testsuite/test_vector.py index 12a553e02e2..a57856eca45 100644 --- a/python/grass/pygrass/vector/testsuite/test_vector.py +++ b/python/grass/pygrass/vector/testsuite/test_vector.py @@ -3,6 +3,7 @@ @author: pietro """ + from grass.gunittest.case import TestCase from grass.gunittest.main import test diff --git a/python/grass/pygrass/vector/testsuite/test_vector3d.py b/python/grass/pygrass/vector/testsuite/test_vector3d.py index 25fe46c8914..16ee0fd969e 100644 --- a/python/grass/pygrass/vector/testsuite/test_vector3d.py +++ b/python/grass/pygrass/vector/testsuite/test_vector3d.py @@ -3,6 +3,7 @@ @author: pietro """ + import numpy as np from grass.gunittest.case import TestCase diff --git a/python/grass/script/task.py b/python/grass/script/task.py index 1c4e29f69a6..325b5640edc 100644 --- a/python/grass/script/task.py +++ b/python/grass/script/task.py @@ -17,6 +17,7 @@ .. sectionauthor:: Martin Landa """ + import os import re import sys diff --git a/python/grass/script/vector.py b/python/grass/script/vector.py index 6b0c9efe2b2..4297fa0171f 100644 --- a/python/grass/script/vector.py +++ b/python/grass/script/vector.py @@ -16,6 +16,7 @@ .. sectionauthor:: Glynn Clements .. sectionauthor:: Martin Landa """ + import os from .utils import parse_key_val diff --git a/python/grass/temporal/abstract_dataset.py b/python/grass/temporal/abstract_dataset.py index 4d6d4d81b51..720b2210ad8 100644 --- a/python/grass/temporal/abstract_dataset.py +++ b/python/grass/temporal/abstract_dataset.py @@ -9,6 +9,7 @@ :authors: Soeren Gebbert """ + from abc import ABCMeta, abstractmethod from .core import ( get_tgis_message_interface, diff --git a/python/grass/temporal/abstract_map_dataset.py b/python/grass/temporal/abstract_map_dataset.py index 035e64c7622..7306133251b 100644 --- a/python/grass/temporal/abstract_map_dataset.py +++ b/python/grass/temporal/abstract_map_dataset.py @@ -9,6 +9,7 @@ :authors: Soeren Gebbert """ + import grass.script as gs from grass.exceptions import ImplementationError from datetime import datetime diff --git a/python/grass/temporal/abstract_space_time_dataset.py b/python/grass/temporal/abstract_space_time_dataset.py index d7e28427190..b4812361174 100644 --- a/python/grass/temporal/abstract_space_time_dataset.py +++ b/python/grass/temporal/abstract_space_time_dataset.py @@ -9,6 +9,7 @@ class that is the base class for all space time datasets. :authors: Soeren Gebbert """ + import sys import uuid import os diff --git a/python/grass/temporal/base.py b/python/grass/temporal/base.py index 1f2b6290aa6..84d247449ff 100644 --- a/python/grass/temporal/base.py +++ b/python/grass/temporal/base.py @@ -24,6 +24,7 @@ :author: Soeren Gebbert """ + from datetime import datetime from .core import ( get_tgis_message_interface, diff --git a/python/grass/temporal/core.py b/python/grass/temporal/core.py index 4b7fe953b51..56d3b4cb77e 100644 --- a/python/grass/temporal/core.py +++ b/python/grass/temporal/core.py @@ -28,6 +28,7 @@ :author: Soeren Gebbert """ + # import traceback import os import grass.script as gscript diff --git a/python/grass/temporal/datetime_math.py b/python/grass/temporal/datetime_math.py index 66bee770ead..3cd30120788 100644 --- a/python/grass/temporal/datetime_math.py +++ b/python/grass/temporal/datetime_math.py @@ -8,6 +8,7 @@ :authors: Soeren Gebbert """ + from datetime import datetime, timedelta from .core import get_tgis_message_interface import copy diff --git a/python/grass/temporal/extract.py b/python/grass/temporal/extract.py index 9cb91ac2230..3f8c9cb0738 100644 --- a/python/grass/temporal/extract.py +++ b/python/grass/temporal/extract.py @@ -8,6 +8,7 @@ :authors: Soeren Gebbert """ + from .core import ( get_tgis_message_interface, get_current_mapset, diff --git a/python/grass/temporal/factory.py b/python/grass/temporal/factory.py index cc3652ff4ca..b7ef8ab5218 100644 --- a/python/grass/temporal/factory.py +++ b/python/grass/temporal/factory.py @@ -17,6 +17,7 @@ :authors: Soeren Gebbert """ + from .core import get_tgis_message_interface from .space_time_datasets import ( SpaceTimeRaster3DDataset, diff --git a/python/grass/temporal/gui_support.py b/python/grass/temporal/gui_support.py index 44e32b6e2e8..09b858657bc 100644 --- a/python/grass/temporal/gui_support.py +++ b/python/grass/temporal/gui_support.py @@ -9,6 +9,7 @@ :authors: Soeren Gebbert """ + from .core import get_available_temporal_mapsets, init_dbif from .factory import dataset_factory import grass.script as gscript diff --git a/python/grass/temporal/list_stds.py b/python/grass/temporal/list_stds.py index 785bb9217f6..0a216bedcd2 100644 --- a/python/grass/temporal/list_stds.py +++ b/python/grass/temporal/list_stds.py @@ -443,11 +443,13 @@ def check_columns(column_names, output_format, element_type): ).format( name=dataset.get_id(), element_type=element_type, - detail=_( - "Dataset is empty or where clause is too constrained or incorrect" - ) - if where - else _("Dataset is empty"), + detail=( + _( + "Dataset is empty or where clause is too constrained or incorrect" + ) + if where + else _("Dataset is empty") + ), ) ) if connection_state_changed: diff --git a/python/grass/temporal/mapcalc.py b/python/grass/temporal/mapcalc.py index e23d8cac165..54edeab885d 100644 --- a/python/grass/temporal/mapcalc.py +++ b/python/grass/temporal/mapcalc.py @@ -8,6 +8,7 @@ :authors: Soeren Gebbert """ + import copy from datetime import datetime from multiprocessing import Process diff --git a/python/grass/temporal/metadata.py b/python/grass/temporal/metadata.py index b9bd7adcc41..a77c16b9850 100644 --- a/python/grass/temporal/metadata.py +++ b/python/grass/temporal/metadata.py @@ -21,6 +21,7 @@ :authors: Soeren Gebbert """ + from .base import SQLDatabaseInterface from .core import SQLDatabaseInterfaceConnection, get_tgis_db_version_from_metadata diff --git a/python/grass/temporal/open_stds.py b/python/grass/temporal/open_stds.py index 837f1a860a7..83aacc1c819 100644 --- a/python/grass/temporal/open_stds.py +++ b/python/grass/temporal/open_stds.py @@ -17,6 +17,7 @@ :authors: Soeren Gebbert """ + from .core import init_dbif, get_current_mapset, get_tgis_message_interface from .factory import dataset_factory from .abstract_map_dataset import AbstractMapDataset diff --git a/python/grass/temporal/register.py b/python/grass/temporal/register.py index 7514cb33d03..323a798d876 100644 --- a/python/grass/temporal/register.py +++ b/python/grass/temporal/register.py @@ -16,6 +16,7 @@ :authors: Soeren Gebbert """ + from datetime import datetime import grass.script as gscript from .core import get_tgis_message_interface, init_dbif, get_current_mapset diff --git a/python/grass/temporal/sampling.py b/python/grass/temporal/sampling.py index 38fdd1aed53..afe84ce57b3 100644 --- a/python/grass/temporal/sampling.py +++ b/python/grass/temporal/sampling.py @@ -16,6 +16,7 @@ :authors: Soeren Gebbert """ + from .core import ( get_current_mapset, get_tgis_message_interface, diff --git a/python/grass/temporal/space_time_datasets.py b/python/grass/temporal/space_time_datasets.py index df1da106e0c..372f32900a1 100644 --- a/python/grass/temporal/space_time_datasets.py +++ b/python/grass/temporal/space_time_datasets.py @@ -8,6 +8,7 @@ :authors: Soeren Gebbert """ + import getpass from .abstract_map_dataset import AbstractMapDataset from .abstract_space_time_dataset import AbstractSpaceTimeDataset diff --git a/python/grass/temporal/spatial_extent.py b/python/grass/temporal/spatial_extent.py index 4288b7eadc6..ced1f88a9a1 100644 --- a/python/grass/temporal/spatial_extent.py +++ b/python/grass/temporal/spatial_extent.py @@ -33,6 +33,7 @@ :authors: Soeren Gebbert """ + from .base import SQLDatabaseInterface diff --git a/python/grass/temporal/spatial_topology_dataset_connector.py b/python/grass/temporal/spatial_topology_dataset_connector.py index 104a1491e39..0f303e5e663 100644 --- a/python/grass/temporal/spatial_topology_dataset_connector.py +++ b/python/grass/temporal/spatial_topology_dataset_connector.py @@ -13,6 +13,7 @@ :authors: Soeren Gebbert """ + import copy diff --git a/python/grass/temporal/spatio_temporal_relationships.py b/python/grass/temporal/spatio_temporal_relationships.py index cfc56644262..14b81ed40d4 100644 --- a/python/grass/temporal/spatio_temporal_relationships.py +++ b/python/grass/temporal/spatio_temporal_relationships.py @@ -17,6 +17,7 @@ :authors: Soeren Gebbert """ + from datetime import datetime from .core import init_dbif from .abstract_dataset import AbstractDatasetComparisonKeyStartTime diff --git a/python/grass/temporal/temporal_algebra.py b/python/grass/temporal/temporal_algebra.py index bd74d6799ff..b8f71ff0655 100644 --- a/python/grass/temporal/temporal_algebra.py +++ b/python/grass/temporal/temporal_algebra.py @@ -796,12 +796,12 @@ def __init__( self.process_chain_dict = ( {} ) # This dictionary stores all processes, as well as the maps to register and remove - self.process_chain_dict[ - "processes" - ] = [] # The mapcalc and v.patch module calls - self.process_chain_dict[ - "register" - ] = [] # Maps that must be registered/updated or inserted in a new STDS + self.process_chain_dict["processes"] = ( + [] + ) # The mapcalc and v.patch module calls + self.process_chain_dict["register"] = ( + [] + ) # Maps that must be registered/updated or inserted in a new STDS self.process_chain_dict["remove"] = [] # The g.remove module calls self.process_chain_dict["STDS"] = {} # The STDS that must be created diff --git a/python/grass/temporal/temporal_extent.py b/python/grass/temporal/temporal_extent.py index 4d033c89102..066f1697462 100644 --- a/python/grass/temporal/temporal_extent.py +++ b/python/grass/temporal/temporal_extent.py @@ -19,6 +19,7 @@ :authors: Soeren Gebbert """ + from .base import SQLDatabaseInterface ############################################################################### diff --git a/python/grass/temporal/temporal_granularity.py b/python/grass/temporal/temporal_granularity.py index df7eb949b0f..a7c47c045d2 100644 --- a/python/grass/temporal/temporal_granularity.py +++ b/python/grass/temporal/temporal_granularity.py @@ -17,6 +17,7 @@ :authors: Soeren Gebbert """ + from .datetime_math import compute_datetime_delta from .abstract_map_dataset import AbstractMapDataset from functools import reduce diff --git a/python/grass/temporal/temporal_operator.py b/python/grass/temporal/temporal_operator.py index f2a5a57bb1c..d86aab8adbd 100644 --- a/python/grass/temporal/temporal_operator.py +++ b/python/grass/temporal/temporal_operator.py @@ -139,6 +139,7 @@ SyntaxError: Unknown optype rter, must be one of ['select', 'boolean', 'raster', 'hash', 'relation', 'overlay'] """ + try: import ply.lex as lex import ply.yacc as yacc diff --git a/python/grass/temporal/temporal_raster3d_algebra.py b/python/grass/temporal/temporal_raster3d_algebra.py index 536f035130c..88d44768b6a 100644 --- a/python/grass/temporal/temporal_raster3d_algebra.py +++ b/python/grass/temporal/temporal_raster3d_algebra.py @@ -10,6 +10,7 @@ :authors: Thomas Leppelt and Soeren Gebbert """ + try: import ply.yacc as yacc except ImportError: diff --git a/python/grass/temporal/temporal_raster_base_algebra.py b/python/grass/temporal/temporal_raster_base_algebra.py index 12daadf2f3b..3fb3d31ad2a 100644 --- a/python/grass/temporal/temporal_raster_base_algebra.py +++ b/python/grass/temporal/temporal_raster_base_algebra.py @@ -40,6 +40,7 @@ LexToken(NAME,'B',1,23) """ + import copy import grass.pygrass.modules as pymod diff --git a/python/grass/temporal/temporal_topology_dataset_connector.py b/python/grass/temporal/temporal_topology_dataset_connector.py index 4a105bee033..a75a13ef54f 100644 --- a/python/grass/temporal/temporal_topology_dataset_connector.py +++ b/python/grass/temporal/temporal_topology_dataset_connector.py @@ -15,6 +15,7 @@ :authors: Soeren Gebbert """ + import copy diff --git a/python/grass/temporal/temporal_vector_algebra.py b/python/grass/temporal/temporal_vector_algebra.py index 5e545e08574..87341fb2c58 100644 --- a/python/grass/temporal/temporal_vector_algebra.py +++ b/python/grass/temporal/temporal_vector_algebra.py @@ -41,6 +41,7 @@ LexToken(RPAREN,')',1,16) """ + try: import ply.yacc as yacc except ImportError: diff --git a/python/grass/temporal/testsuite/unittests_temporal_raster3d_algebra.py b/python/grass/temporal/testsuite/unittests_temporal_raster3d_algebra.py index fd011a55d53..1ed80cd1316 100644 --- a/python/grass/temporal/testsuite/unittests_temporal_raster3d_algebra.py +++ b/python/grass/temporal/testsuite/unittests_temporal_raster3d_algebra.py @@ -7,7 +7,6 @@ :authors: Soeren Gebbert and Thomas Leppelt """ - import grass.script import grass.temporal as tgis from grass.gunittest.case import TestCase diff --git a/python/grass/temporal/unit_tests.py b/python/grass/temporal/unit_tests.py index fd412ee6cf2..8083680ef3f 100644 --- a/python/grass/temporal/unit_tests.py +++ b/python/grass/temporal/unit_tests.py @@ -8,6 +8,7 @@ :authors: Soeren Gebbert """ + import copy from datetime import datetime import grass.script.core as core diff --git a/python/grass/temporal/univar_statistics.py b/python/grass/temporal/univar_statistics.py index 80cca737199..bb5475aec1e 100755 --- a/python/grass/temporal/univar_statistics.py +++ b/python/grass/temporal/univar_statistics.py @@ -18,6 +18,7 @@ :authors: Soeren Gebbert """ + from multiprocessing import Pool from subprocess import PIPE diff --git a/raster/r.basins.fill/testsuite/testrbf.py b/raster/r.basins.fill/testsuite/testrbf.py index fdbcd4b548f..b9937b05689 100644 --- a/raster/r.basins.fill/testsuite/testrbf.py +++ b/raster/r.basins.fill/testsuite/testrbf.py @@ -8,6 +8,7 @@ License (>=v2). Read the file COPYING that comes with GRASS for details. """ + import unittest from grass.gunittest.case import TestCase diff --git a/raster/r.external/testsuite/test_r_external.py b/raster/r.external/testsuite/test_r_external.py index 839a724a5b7..a22498eb773 100644 --- a/raster/r.external/testsuite/test_r_external.py +++ b/raster/r.external/testsuite/test_r_external.py @@ -2,6 +2,7 @@ @author Markus Neteler """ + from grass.gunittest.case import TestCase diff --git a/raster/r.gwflow/testsuite/validation_7x7_grid.py b/raster/r.gwflow/testsuite/validation_7x7_grid.py index f4595eaf421..6d632092300 100644 --- a/raster/r.gwflow/testsuite/validation_7x7_grid.py +++ b/raster/r.gwflow/testsuite/validation_7x7_grid.py @@ -7,6 +7,7 @@ @author Soeren Gebbert """ + from grass.gunittest.case import TestCase diff --git a/raster/r.horizon/testsuite/test_r_horizon.py b/raster/r.horizon/testsuite/test_r_horizon.py index 4118c1cb203..846988401dc 100644 --- a/raster/r.horizon/testsuite/test_r_horizon.py +++ b/raster/r.horizon/testsuite/test_r_horizon.py @@ -11,6 +11,7 @@ License (>=v2). Read the file COPYING that comes with GRASS for details. """ + import json from grass.gunittest.case import TestCase diff --git a/raster/r.in.ascii/testsuite/test_r_in_ascii.py b/raster/r.in.ascii/testsuite/test_r_in_ascii.py index 151b6ff7978..20e0c2a8f9e 100644 --- a/raster/r.in.ascii/testsuite/test_r_in_ascii.py +++ b/raster/r.in.ascii/testsuite/test_r_in_ascii.py @@ -8,6 +8,7 @@ License (>=v2). Read the file COPYING that comes with GRASS for details. """ + from grass.gunittest.case import TestCase from grass.gunittest.main import test from grass.script.core import read_command diff --git a/raster/r.in.gdal/testsuite/test_r_in_gdal.py b/raster/r.in.gdal/testsuite/test_r_in_gdal.py index 3e3f6bcd554..2b8bee0982a 100644 --- a/raster/r.in.gdal/testsuite/test_r_in_gdal.py +++ b/raster/r.in.gdal/testsuite/test_r_in_gdal.py @@ -2,6 +2,7 @@ @author Soeren Gebbert """ + from grass.gunittest.case import TestCase diff --git a/raster/r.info/testsuite/test_r_info.py b/raster/r.info/testsuite/test_r_info.py index 05953ae56b4..a4d554232dd 100644 --- a/raster/r.info/testsuite/test_r_info.py +++ b/raster/r.info/testsuite/test_r_info.py @@ -8,6 +8,7 @@ License (>=v2). Read the file COPYING that comes with GRASS for details. """ + from grass.gunittest.case import TestCase from grass.gunittest.gmodules import SimpleModule diff --git a/raster/r.random.cells/testsuite/test_random_cells.py b/raster/r.random.cells/testsuite/test_random_cells.py index 9faeb3b0135..0d4ca4379e5 100644 --- a/raster/r.random.cells/testsuite/test_random_cells.py +++ b/raster/r.random.cells/testsuite/test_random_cells.py @@ -12,7 +12,6 @@ for details. """ - from grass.gunittest.case import TestCase from grass.gunittest.main import test diff --git a/raster/r.random/testsuite/testrandom.py b/raster/r.random/testsuite/testrandom.py index 791aebfa669..e2bc2e413a3 100644 --- a/raster/r.random/testsuite/testrandom.py +++ b/raster/r.random/testsuite/testrandom.py @@ -8,6 +8,7 @@ License (>=v2). Read the file COPYING that comes with GRASS for details. """ + from grass.gunittest.case import TestCase from grass.gunittest.main import test from grass.gunittest.gmodules import SimpleModule diff --git a/raster/r.reclass/testsuite/test_r_reclass.py b/raster/r.reclass/testsuite/test_r_reclass.py index 71d63d1c4bb..3f4ecfdf6a3 100644 --- a/raster/r.reclass/testsuite/test_r_reclass.py +++ b/raster/r.reclass/testsuite/test_r_reclass.py @@ -8,6 +8,7 @@ License (>=v2). Read the file COPYING that comes with GRASS for details. """ + from grass.gunittest.case import TestCase from grass.gunittest.main import test from grass.gunittest.gmodules import SimpleModule diff --git a/raster/r.series.interp/testsuite/interp_test.py b/raster/r.series.interp/testsuite/interp_test.py index 017912172be..e4cadd251cd 100644 --- a/raster/r.series.interp/testsuite/interp_test.py +++ b/raster/r.series.interp/testsuite/interp_test.py @@ -1,6 +1,7 @@ """Test of r.series.interp @author Soeren Gebbert """ + from grass.gunittest.case import TestCase diff --git a/raster/r.support/testsuite/test_r_support.py b/raster/r.support/testsuite/test_r_support.py index f7b7dd9e917..9a024c4a723 100644 --- a/raster/r.support/testsuite/test_r_support.py +++ b/raster/r.support/testsuite/test_r_support.py @@ -8,6 +8,7 @@ Read the file COPYING that comes with GRASS for details """ + import random import string diff --git a/raster/r.texture/testsuite/test_texture.py b/raster/r.texture/testsuite/test_texture.py index af24229e9ba..378eaaeabb5 100644 --- a/raster/r.texture/testsuite/test_texture.py +++ b/raster/r.texture/testsuite/test_texture.py @@ -8,6 +8,7 @@ License (>=v2). Read the file COPYING that comes with GRASS for details. """ + from grass.gunittest.case import TestCase diff --git a/raster/r.tile/testsuite/testrt.py b/raster/r.tile/testsuite/testrt.py index c1da1d10cdf..6cb5a91c296 100644 --- a/raster/r.tile/testsuite/testrt.py +++ b/raster/r.tile/testsuite/testrt.py @@ -8,6 +8,7 @@ License (>=v2). Read the file COPYING that comes with GRASS for details. """ + from grass.gunittest.case import TestCase from grass.gunittest.main import test diff --git a/raster/r.to.vect/testsuite/test_r_to_vect.py b/raster/r.to.vect/testsuite/test_r_to_vect.py index 57de45e4b77..7ba284d0261 100644 --- a/raster/r.to.vect/testsuite/test_r_to_vect.py +++ b/raster/r.to.vect/testsuite/test_r_to_vect.py @@ -8,6 +8,7 @@ License (>=v2). Read the file COPYING that comes with GRASS for details. """ + from grass.gunittest.case import TestCase from grass.gunittest.main import test diff --git a/raster/r.univar/testsuite/test_r_univar.py b/raster/r.univar/testsuite/test_r_univar.py index 368ff3faae0..c03aea5dcfa 100644 --- a/raster/r.univar/testsuite/test_r_univar.py +++ b/raster/r.univar/testsuite/test_r_univar.py @@ -2,6 +2,7 @@ @author Soeren Gebbert """ + from grass.gunittest.case import TestCase diff --git a/raster/r.what/testsuite/testrw.py b/raster/r.what/testsuite/testrw.py index f63ae5dfe30..8184f534720 100644 --- a/raster/r.what/testsuite/testrw.py +++ b/raster/r.what/testsuite/testrw.py @@ -8,6 +8,7 @@ License (>=v2). Read the file COPYING that comes with GRASS for details. """ + from grass.gunittest.case import TestCase from grass.gunittest.main import test from grass.gunittest.gmodules import SimpleModule diff --git a/raster3d/r3.flow/testsuite/r3flow_test.py b/raster3d/r3.flow/testsuite/r3flow_test.py index 8385f10559e..f7d013f38bd 100644 --- a/raster3d/r3.flow/testsuite/r3flow_test.py +++ b/raster3d/r3.flow/testsuite/r3flow_test.py @@ -3,6 +3,7 @@ @author Anna Petrasova """ + import os from grass.gunittest.case import TestCase from grass.gunittest.main import test diff --git a/raster3d/r3.gradient/testsuite/r3gradient_test.py b/raster3d/r3.gradient/testsuite/r3gradient_test.py index 9d0814dac78..d41e0a74baa 100644 --- a/raster3d/r3.gradient/testsuite/r3gradient_test.py +++ b/raster3d/r3.gradient/testsuite/r3gradient_test.py @@ -3,6 +3,7 @@ @author Anna Petrasova """ + from grass.gunittest.case import TestCase from grass.gunittest.main import test diff --git a/scripts/r.fillnulls/testsuite/test_r_fillnulls.py b/scripts/r.fillnulls/testsuite/test_r_fillnulls.py index 8cfed138f4e..975fd5330f2 100644 --- a/scripts/r.fillnulls/testsuite/test_r_fillnulls.py +++ b/scripts/r.fillnulls/testsuite/test_r_fillnulls.py @@ -3,6 +3,7 @@ @author: Sanjeet Bhatti """ + import os from grass.gunittest.case import TestCase diff --git a/scripts/r.in.wms/srs.py b/scripts/r.in.wms/srs.py index 43ee8747eb2..6840e72dca5 100644 --- a/scripts/r.in.wms/srs.py +++ b/scripts/r.in.wms/srs.py @@ -11,6 +11,7 @@ @author Stepan Turek (Based on code from OWSLib - Copyright below) """ + # -*- coding: ISO-8859-15 -*- # ============================================================================= # Copyright (c) 2011 Tom Kralidis diff --git a/scripts/r.in.wms/wms_cap_parsers.py b/scripts/r.in.wms/wms_cap_parsers.py index 6846124efa3..8418bbdbbe6 100644 --- a/scripts/r.in.wms/wms_cap_parsers.py +++ b/scripts/r.in.wms/wms_cap_parsers.py @@ -16,6 +16,7 @@ @author Stepan Turek (Mentor: Martin Landa) """ + import pathlib from xml.etree.ElementTree import ParseError diff --git a/scripts/r.mapcalc.simple/testsuite/test_rmapcalcsimple.py b/scripts/r.mapcalc.simple/testsuite/test_rmapcalcsimple.py index 70da5f40b11..d400ccc7980 100644 --- a/scripts/r.mapcalc.simple/testsuite/test_rmapcalcsimple.py +++ b/scripts/r.mapcalc.simple/testsuite/test_rmapcalcsimple.py @@ -8,6 +8,7 @@ License (>=v2). Read the file COPYING that comes with GRASS for details. """ + from grass.gunittest.case import TestCase diff --git a/scripts/r.reclass.area/testsuite/testrra.py b/scripts/r.reclass.area/testsuite/testrra.py index 6c7822c0f6c..e6e2300875b 100644 --- a/scripts/r.reclass.area/testsuite/testrra.py +++ b/scripts/r.reclass.area/testsuite/testrra.py @@ -8,6 +8,7 @@ License (>=v2). Read the file COPYING that comes with GRASS for details. """ + from grass.gunittest.case import TestCase from grass.gunittest.main import test diff --git a/scripts/v.rast.stats/testsuite/test_v_rast_stats.py b/scripts/v.rast.stats/testsuite/test_v_rast_stats.py index 4b411bf6666..ca3111d14d8 100644 --- a/scripts/v.rast.stats/testsuite/test_v_rast_stats.py +++ b/scripts/v.rast.stats/testsuite/test_v_rast_stats.py @@ -2,6 +2,7 @@ @author Soeren Gebbert """ + from grass.gunittest.case import TestCase from grass.gunittest.gmodules import SimpleModule from grass.pygrass.vector import VectorTopo diff --git a/temporal/t.rast.aggregate/testsuite/test_aggregation_absolute.py b/temporal/t.rast.aggregate/testsuite/test_aggregation_absolute.py index 2056a654f7c..c5eb4618d92 100644 --- a/temporal/t.rast.aggregate/testsuite/test_aggregation_absolute.py +++ b/temporal/t.rast.aggregate/testsuite/test_aggregation_absolute.py @@ -7,6 +7,7 @@ :authors: Soeren Gebbert """ + import os import grass.pygrass.modules as pymod import grass.temporal as tgis diff --git a/temporal/t.rast.aggregate/testsuite/test_aggregation_absolute_parallel.py b/temporal/t.rast.aggregate/testsuite/test_aggregation_absolute_parallel.py index f70c150c7c0..ac6471398ad 100644 --- a/temporal/t.rast.aggregate/testsuite/test_aggregation_absolute_parallel.py +++ b/temporal/t.rast.aggregate/testsuite/test_aggregation_absolute_parallel.py @@ -7,6 +7,7 @@ :authors: Soeren Gebbert """ + import os import grass.pygrass.modules as pymod import grass.temporal as tgis diff --git a/temporal/t.rast.aggregate/testsuite/test_aggregation_relative.py b/temporal/t.rast.aggregate/testsuite/test_aggregation_relative.py index 265d4f82465..fe53844feea 100644 --- a/temporal/t.rast.aggregate/testsuite/test_aggregation_relative.py +++ b/temporal/t.rast.aggregate/testsuite/test_aggregation_relative.py @@ -7,6 +7,7 @@ :authors: Soeren Gebbert """ + import os import grass.pygrass.modules as pymod import grass.temporal as tgis diff --git a/temporal/t.rast.series/testsuite/test_series.py b/temporal/t.rast.series/testsuite/test_series.py index 4eb41f80f1a..7b9df7921b7 100644 --- a/temporal/t.rast.series/testsuite/test_series.py +++ b/temporal/t.rast.series/testsuite/test_series.py @@ -7,6 +7,7 @@ :authors: Soeren Gebbert """ + import os import grass.pygrass.modules as pymod import grass.temporal as tgis diff --git a/temporal/t.rast3d.algebra/testsuite/test_raster3d_algebra.py b/temporal/t.rast3d.algebra/testsuite/test_raster3d_algebra.py index 59d47a1dacd..980ec553119 100644 --- a/temporal/t.rast3d.algebra/testsuite/test_raster3d_algebra.py +++ b/temporal/t.rast3d.algebra/testsuite/test_raster3d_algebra.py @@ -7,7 +7,6 @@ :authors: Soeren Gebbert and Thomas Leppelt """ - import grass.script import grass.temporal as tgis from grass.gunittest.case import TestCase diff --git a/temporal/t.shift/testsuite/test_shift.py b/temporal/t.shift/testsuite/test_shift.py index 1c1f29f03d9..eff9a5f5702 100644 --- a/temporal/t.shift/testsuite/test_shift.py +++ b/temporal/t.shift/testsuite/test_shift.py @@ -7,6 +7,7 @@ :authors: Soeren Gebbert """ + import os import grass.pygrass.modules as pymod import grass.temporal as tgis diff --git a/temporal/t.snap/testsuite/test_snap.py b/temporal/t.snap/testsuite/test_snap.py index e16acc52a57..5d8c0bbe166 100644 --- a/temporal/t.snap/testsuite/test_snap.py +++ b/temporal/t.snap/testsuite/test_snap.py @@ -7,6 +7,7 @@ :authors: Soeren Gebbert """ + import os import grass.pygrass.modules as pymod import grass.temporal as tgis diff --git a/temporal/t.support/testsuite/test_support_str3ds.py b/temporal/t.support/testsuite/test_support_str3ds.py index 4e2a1d30123..613b5e9bbc3 100644 --- a/temporal/t.support/testsuite/test_support_str3ds.py +++ b/temporal/t.support/testsuite/test_support_str3ds.py @@ -7,6 +7,7 @@ :authors: Soeren Gebbert """ + import os import grass.pygrass.modules as pymod import grass.temporal as tgis diff --git a/temporal/t.support/testsuite/test_support_strds.py b/temporal/t.support/testsuite/test_support_strds.py index a618f94bc5b..40692693c34 100644 --- a/temporal/t.support/testsuite/test_support_strds.py +++ b/temporal/t.support/testsuite/test_support_strds.py @@ -7,6 +7,7 @@ :authors: Soeren Gebbert """ + import os import grass.pygrass.modules as pymod import grass.temporal as tgis diff --git a/temporal/t.support/testsuite/test_support_stvds.py b/temporal/t.support/testsuite/test_support_stvds.py index 256e3a9b98f..2cd973c2119 100644 --- a/temporal/t.support/testsuite/test_support_stvds.py +++ b/temporal/t.support/testsuite/test_support_stvds.py @@ -7,6 +7,7 @@ :authors: Soeren Gebbert """ + import os import grass.pygrass.modules as pymod import grass.temporal as tgis diff --git a/temporal/t.unregister/testsuite/test_unregister.py b/temporal/t.unregister/testsuite/test_unregister.py index 6cf54e482e2..fa011b9edaa 100644 --- a/temporal/t.unregister/testsuite/test_unregister.py +++ b/temporal/t.unregister/testsuite/test_unregister.py @@ -7,6 +7,7 @@ :authors: Soeren Gebbert """ + import os import grass.pygrass.modules as pymod import grass.temporal as tgis diff --git a/vector/v.extract/testsuite/test_v_extract.py b/vector/v.extract/testsuite/test_v_extract.py index ff0c8b590a3..d266e8ad649 100644 --- a/vector/v.extract/testsuite/test_v_extract.py +++ b/vector/v.extract/testsuite/test_v_extract.py @@ -8,6 +8,7 @@ License (>=v2). Read the file COPYING that comes with GRASS for details. """ + import os from grass.gunittest.case import TestCase from grass.gunittest.gmodules import SimpleModule diff --git a/vector/v.fill.holes/examples.ipynb b/vector/v.fill.holes/examples.ipynb index 28d86332b0a..fcc006501e4 100644 --- a/vector/v.fill.holes/examples.ipynb +++ b/vector/v.fill.holes/examples.ipynb @@ -82,7 +82,7 @@ "outputs": [], "source": [ "!g.region vector=data grow=3 res=1\n", - "text_position = (75,5)" + "text_position = (75, 5)" ] }, { @@ -144,7 +144,7 @@ "source": [ "!g.region vector=dissolve_data grow=2 res=1\n", "\n", - "text_position = (75,5)\n", + "text_position = (75, 5)\n", "\n", "plot = gj.Map(use_region=True, width=700)\n", "plot.d_background(color=\"white\")\n", @@ -209,7 +209,7 @@ "plot = gj.Map(use_region=True, width=700)\n", "plot.d_background(color=\"white\")\n", "plot.d_vect(map=\"lakes_only\", legend_label=\"Original\")\n", - "plot.d_legend_vect(flags=\"b\", at=(60,10))\n", + "plot.d_legend_vect(flags=\"b\", at=(60, 10))\n", "plot.show()" ] }, @@ -231,7 +231,7 @@ "plot = gj.Map(use_region=True, width=700)\n", "plot.d_background(color=\"white\")\n", "plot.d_vect(map=\"lakes_filled\", legend_label=\"Filled\")\n", - "plot.d_legend_vect(flags=\"b\", at=(60,10))\n", + "plot.d_legend_vect(flags=\"b\", at=(60, 10))\n", "plot.show()" ] }, @@ -253,7 +253,7 @@ "plot = gj.Map(use_region=True, width=700)\n", "plot.d_background(color=\"white\")\n", "plot.d_vect(map=\"lakes_dissolved\", legend_label=\"Dissolved\")\n", - "plot.d_legend_vect(flags=\"b\", at=(60,10))\n", + "plot.d_legend_vect(flags=\"b\", at=(60, 10))\n", "plot.show()" ] }, @@ -265,9 +265,17 @@ "source": [ "plot = gj.Map(use_region=True, width=1024)\n", "plot.d_background(color=\"#E28A2B\")\n", - "plot.d_vect(map=\"lakes_filled\", color=\"none\", fill_color=\"#384C6B\", legend_label=\"Filled\")\n", - "plot.d_vect(map=\"lakes_only\", color=\"#859BBA\", fill_color=\"none\", width=2, legend_label=\"Original\")\n", - "plot.d_legend_vect(flags=\"b\", at=(80,85), fontsize=22, symbol_size=35)\n", + "plot.d_vect(\n", + " map=\"lakes_filled\", color=\"none\", fill_color=\"#384C6B\", legend_label=\"Filled\"\n", + ")\n", + "plot.d_vect(\n", + " map=\"lakes_only\",\n", + " color=\"#859BBA\",\n", + " fill_color=\"none\",\n", + " width=2,\n", + " legend_label=\"Original\",\n", + ")\n", + "plot.d_legend_vect(flags=\"b\", at=(80, 85), fontsize=22, symbol_size=35)\n", "filename = \"v_fill_holes.png\"\n", "plot.save(filename)\n", "!mogrify -trim {filename}\n", diff --git a/vector/v.in.ogr/testsuite/test_v_in_ogr.py b/vector/v.in.ogr/testsuite/test_v_in_ogr.py index 7257c44b0ee..167cd8747e8 100644 --- a/vector/v.in.ogr/testsuite/test_v_in_ogr.py +++ b/vector/v.in.ogr/testsuite/test_v_in_ogr.py @@ -2,6 +2,7 @@ @author Markus Neteler """ + from grass.gunittest.case import TestCase from grass.gunittest.gmodules import SimpleModule diff --git a/vector/v.to.rast/testsuite/test_v_to_rast.py b/vector/v.to.rast/testsuite/test_v_to_rast.py index 273c77983d8..352b8c578f3 100644 --- a/vector/v.to.rast/testsuite/test_v_to_rast.py +++ b/vector/v.to.rast/testsuite/test_v_to_rast.py @@ -11,6 +11,7 @@ License (>=v2). Read the file COPYING that comes with GRASS for details. """ + from grass.gunittest.case import TestCase from grass.gunittest.main import test diff --git a/vector/v.univar/testsuite/v_univar_test.py b/vector/v.univar/testsuite/v_univar_test.py index 3b9c75b7d70..33fd0425c1d 100644 --- a/vector/v.univar/testsuite/v_univar_test.py +++ b/vector/v.univar/testsuite/v_univar_test.py @@ -8,6 +8,7 @@ License (>=v2). Read the file COPYING that comes with GRASS for details. """ + from grass.gunittest.case import TestCase from grass.gunittest.main import test from grass.gunittest.gmodules import SimpleModule diff --git a/vector/v.vect.stats/testsuite/test_vect_stats.py b/vector/v.vect.stats/testsuite/test_vect_stats.py index 8d7cf0e6c18..fe982ceff33 100644 --- a/vector/v.vect.stats/testsuite/test_vect_stats.py +++ b/vector/v.vect.stats/testsuite/test_vect_stats.py @@ -8,6 +8,7 @@ License (>=v2). Read the file COPYING that comes with GRASS for details. """ + from grass.gunittest.case import TestCase from grass.gunittest.main import test from grass.gunittest.gmodules import SimpleModule From 47536d0b526ddd507149db653a8fd81f34fc2f31 Mon Sep 17 00:00:00 2001 From: Stefan Blumentrath Date: Wed, 24 Apr 2024 10:50:06 +0200 Subject: [PATCH 20/27] temporal: update raster map metadata from file DB when overwrite is true (#3374) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * update from file DB * add history functions * add history functions * linting and some reverts * add tests * use History from libraster * dbif and is_in_db * Update python/grass/temporal/testsuite/test_register_function.py Co-authored-by: Edouard Choinière <27212526+echoix@users.noreply.github.com> * Update python/grass/temporal/testsuite/test_register_function.py Co-authored-by: Edouard Choinière <27212526+echoix@users.noreply.github.com> * avoid duplicate function calls in loop * Update python/grass/temporal/testsuite/test_register_function.py Co-authored-by: Veronica Andreo --------- Co-authored-by: Edouard Choinière <27212526+echoix@users.noreply.github.com> Co-authored-by: Veronica Andreo --- .../grass/temporal/c_libraries_interface.py | 183 ++++++++++ python/grass/temporal/register.py | 327 +++++++++--------- python/grass/temporal/space_time_datasets.py | 37 +- .../testsuite/test_register_function.py | 95 +++-- 4 files changed, 453 insertions(+), 189 deletions(-) diff --git a/python/grass/temporal/c_libraries_interface.py b/python/grass/temporal/c_libraries_interface.py index 4a908e49716..646ccfdd492 100644 --- a/python/grass/temporal/c_libraries_interface.py +++ b/python/grass/temporal/c_libraries_interface.py @@ -51,6 +51,7 @@ class RPCDefs: WRITE_SEMANTIC_LABEL = 15 READ_SEMANTIC_LABEL = 16 REMOVE_SEMANTIC_LABEL = 17 + READ_MAP_HISTORY = 18 G_FATAL_ERROR = 49 TYPE_RASTER = 0 @@ -981,6 +982,142 @@ def _read_vector_info(name, mapset): ############################################################################### +def _read_map_history(lock, conn, data): + """Read map history from the spatial database using C-library functions + + :param lock: A multiprocessing.Lock instance + :param conn: A multiprocessing.Pipe instance used to send True or False + :param data: The list of data entries [function_id, maptype, name, mapset] + """ + kvp = None + try: + maptype = data[1] + name = data[2] + mapset = data[3] + if maptype == RPCDefs.TYPE_RASTER: + kvp = _read_raster_history(name, mapset) + elif maptype == RPCDefs.TYPE_VECTOR: + kvp = _read_vector_history(name, mapset) + elif maptype == RPCDefs.TYPE_RASTER3D: + kvp = _read_raster3d_history(name, mapset) + except: + raise + finally: + conn.send(kvp) + + +############################################################################### + + +def _read_raster_history(name, mapset): + """Read the raster history from the file system and store the content + into a dictionary + + This method uses the ctypes interface to the gis and raster libraries + to read the map history + + :param name: The name of the map + :param mapset: The mapset of the map + :returns: The key value pairs of the map specific metadata, or None in + case of an error + """ + + kvp = {} + + if not libgis.G_find_raster(name, mapset): + return None + + # Read the raster history + hist = libraster.History() + ret = libraster.Rast_read_history(name, mapset, byref(hist)) + if ret < 0: + logging.warning(_("Unable to read history file")) + return None + else: + kvp["creation_time"] = decode( + libraster.Rast_get_history(byref(hist), libraster.HIST_MAPID) + ) + kvp["creator"] = decode( + libraster.Rast_get_history(byref(hist), libraster.HIST_CREATOR) + ) + + return kvp + + +############################################################################### + + +def _read_raster3d_history(name, mapset): + """Read the 3D raster map info from the file system and store the content + into a dictionary + + This method uses the ctypes interface to the gis and raster3d libraries + to read the map metadata information + + :param name: The name of the map + :param mapset: The mapset of the map + :returns: The key value pairs of the map specific metadata, or None in + case of an error + """ + + kvp = {} + + if not libgis.G_find_raster3d(name, mapset): + return None + + # Read the region information + hist = libraster.History() + ret = libraster3d.Rast3d_read_history(name, mapset, byref(hist)) + if ret < 0: + logging.warning(_("Unable to read history file")) + return None + else: + kvp["creation_time"] = decode( + libraster.Rast_get_history(byref(hist), libraster3d.HIST_MAPID) + ) + kvp["creator"] = decode( + libraster.Rast_get_history(byref(hist), libraster3d.HIST_CREATOR) + ) + + return kvp + + +############################################################################### + + +def _read_vector_history(name, mapset): + """Read the vector history from the file system and store the content + into a dictionary + + This method uses the ctypes interface to the gis and raster libraries + to read the map history + + :param name: The name of the map + :param mapset: The mapset of the map + :returns: The key value pairs of the map specific metadata, or None in + case of an error + """ + + kvp = {} + + if not libgis.G_find_vector(name, mapset): + return None + + # Read the vector history + Map = libvector.Map_info() + if libvector.Vect_open_old(byref(Map), name, mapset, "1") > 0: + kvp["creation_time"] = decode(libvector.Vect_get_map_date(byref(Map))) + kvp["creator"] = decode(libvector.Vect_get_person(byref(Map))) + else: + None + libvector.Vect_close(byref(Map)) + + return kvp + + +############################################################################### + + def _convert_timestamp_from_grass(ts): """Convert a GRASS file based timestamp into the temporal framework format datetime or integer. @@ -1124,6 +1261,7 @@ def error_handler(data): functions[RPCDefs.WRITE_SEMANTIC_LABEL] = _write_semantic_label functions[RPCDefs.READ_SEMANTIC_LABEL] = _read_semantic_label functions[RPCDefs.REMOVE_SEMANTIC_LABEL] = _remove_semantic_label + functions[RPCDefs.READ_MAP_HISTORY] = _read_map_history functions[RPCDefs.G_FATAL_ERROR] = _fatal_error libgis.G_gisinit("c_library_server") @@ -1374,6 +1512,21 @@ def read_raster_full_info(self, name, mapset): ) return self.safe_receive("read_raster_full_info") + def read_raster_history(self, name, mapset): + """Read the raster map history from the file system and store the content + into a dictionary + + :param name: The name of the map + :param mapset: The mapset of the map + :returns: The key value pairs of the map history (creation, creation_time), + or None in case of an error + """ + self.check_server() + self.client_conn.send( + [RPCDefs.READ_MAP_HISTORY, RPCDefs.TYPE_RASTER, name, mapset, None] + ) + return self.safe_receive("read_raster_history") + def has_raster_timestamp(self, name, mapset): """Check if a file based raster timestamp exists @@ -1533,6 +1686,21 @@ def read_raster3d_info(self, name, mapset): ) return self.safe_receive("read_raster3d_info") + def read_raster3d_history(self, name, mapset): + """Read the 3D raster map history from the file system and store the content + into a dictionary + + :param name: The name of the map + :param mapset: The mapset of the map + :returns: The key value pairs of the map history (creation, creation_time), + or None in case of an error + """ + self.check_server() + self.client_conn.send( + [RPCDefs.READ_MAP_HISTORY, RPCDefs.TYPE_RASTER3D, name, mapset, None] + ) + return self.safe_receive("read_raster3d_history") + def has_raster3d_timestamp(self, name, mapset): """Check if a file based 3D raster timestamp exists @@ -1655,6 +1823,21 @@ def read_vector_full_info(self, name, mapset): ) return self.safe_receive("read_vector_full_info") + def read_vector_history(self, name, mapset): + """Read the vector map history from the file system and store the content + into a dictionary + + :param name: The name of the map + :param mapset: The mapset of the map + :returns: The key value pairs of the map history (creation, creation_time), + or None in case of an error + """ + self.check_server() + self.client_conn.send( + [RPCDefs.READ_MAP_HISTORY, RPCDefs.TYPE_VECTOR, name, mapset, None] + ) + return self.safe_receive("read_vector_history") + def has_vector_timestamp(self, name, mapset, layer=None): """Check if a file based vector timestamp exists diff --git a/python/grass/temporal/register.py b/python/grass/temporal/register.py index 323a798d876..d0ccbc7aa0c 100644 --- a/python/grass/temporal/register.py +++ b/python/grass/temporal/register.py @@ -18,7 +18,7 @@ """ from datetime import datetime -import grass.script as gscript +import grass.script as gs from .core import get_tgis_message_interface, init_dbif, get_current_mapset from .open_stds import open_old_stds from .abstract_map_dataset import AbstractMapDataset @@ -82,6 +82,7 @@ def register_maps_in_space_time_dataset( start_time_in_file = False end_time_in_file = False semantic_label_in_file = False + overwrite = gs.overwrite() msgr = get_tgis_message_interface() @@ -96,15 +97,13 @@ def register_maps_in_space_time_dataset( increment = str(increment) if maps and file: - msgr.fatal(_("%s= and %s= are mutually exclusive") % ("maps", "file")) + msgr.fatal(_("maps and file are mutually exclusive")) if end and increment: - msgr.fatal(_("%s= and %s= are mutually exclusive") % ("end", "increment")) + msgr.fatal(_("end and increment are mutually exclusive")) if end and interval: - msgr.fatal( - _("%s= and the %s flag are mutually exclusive") % ("end", "interval") - ) + msgr.fatal(_("end and the interval flag are mutually exclusive")) if increment and not start: msgr.fatal(_("The increment option requires the start option")) @@ -113,13 +112,14 @@ def register_maps_in_space_time_dataset( msgr.fatal(_("The interval flag requires the start option")) if end and not start: - msgr.fatal(_("Please specify %s= and %s=") % ("start_time", "end_time")) + msgr.fatal(_("Please specify start_time and end_time")) if not maps and not file: - msgr.fatal(_("Please specify %s= or %s=") % ("maps", "file")) + msgr.fatal(_("Please specify maps or file")) + # We may need the mapset mapset = get_current_mapset() - dbif, connection_state_changed = init_dbif(None) + dbif, connection_state_changed = init_dbif(dbif) # create new stds only in the current mapset # remove all connections to any other mapsets @@ -136,23 +136,17 @@ def register_maps_in_space_time_dataset( dbif.close() msgr.fatal( _( - "Space time %(sp)s dataset <%(name)s> with relative" - " time found, but no relative unit set for %(sp)s " + "Space time {sp} dataset <{name}> with relative" + " time found, but no relative unit set for {sp} " "maps" - ) - % {"name": name, "sp": sp.get_new_map_instance(None).get_type()} + ).format(name=name, sp=sp.get_new_map_instance(None).get_type()) ) maplist = [] # Map names as comma separated string if maps: - if maps.find(",") < 0: - maplist = [ - maps, - ] - else: - maplist = maps.split(",") + maplist = maps.split(",") # Build the map list again with the ids for idx, maplist_item in enumerate(maplist): @@ -242,155 +236,147 @@ def register_maps_in_space_time_dataset( msgr.debug(2, "Gathering map information...") - for count in range(len(maplist)): + for count, row in enumerate(maplist): if count % 50 == 0: msgr.percent(count, num_maps, 1) # Get a new instance of the map type - map = dataset_factory(type, maplist[count]["id"]) + map_object = dataset_factory(type, row["id"]) - if map.map_exists() is not True: + map_object_id = map_object.get_map_id() + map_object_layer = map_object.get_layer() + map_object_type = map_object.get_type() + if not map_object.map_exists(): msgr.fatal( - _("Unable to update %(t)s map <%(id)s>. " "The map does not exist.") - % {"t": map.get_type(), "id": map.get_map_id()} + _("Unable to update {t} map <{mid}>. The map does not exist.").format( + t=map_object_type, mid=map_object_id + ) ) # Use the time data from file - if "start" in maplist[count]: - start = maplist[count]["start"] - if "end" in maplist[count]: - end = maplist[count]["end"] + if "start" in row: + start = row["start"] + if "end" in row: + end = row["end"] # Use the semantic label from file - if "semantic_label" in maplist[count]: - semantic_label = maplist[count]["semantic_label"] + if "semantic_label" in row: + semantic_label = row["semantic_label"] else: semantic_label = None - is_in_db = False + is_in_db = map_object.is_in_db(dbif, mapset) # Put the map into the database of the current mapset - if not map.is_in_db(dbif, mapset): + if not is_in_db: # Break in case no valid time is provided - if (start == "" or start is None) and not map.has_grass_timestamp(): + if (start == "" or start is None) and not map_object.has_grass_timestamp(): dbif.close() - if map.get_layer(): + if map_object_layer: msgr.fatal( _( - "Unable to register %(t)s map <%(id)s> with " - "layer %(l)s. The map has timestamp and " + "Unable to register {t} map <{mid}> with " + "layer {l}. The map has timestamp and " "the start time is not set." + ).format( + t=map_object_type, + mid=map_object_id, + l=map_object_layer, ) - % { - "t": map.get_type(), - "id": map.get_map_id(), - "l": map.get_layer(), - } ) else: msgr.fatal( _( - "Unable to register %(t)s map <%(id)s>. The" + "Unable to register {t} map <{mid}>. The" " map has no timestamp and the start time " "is not set." - ) - % {"t": map.get_type(), "id": map.get_map_id()} + ).format(t=map_object_type, mid=map_object_id) ) if start != "" and start is not None: # We need to check if the time is absolute and the unit was specified time_object = check_datetime_string(start) if isinstance(time_object, datetime) and unit: - msgr.fatal( - _("%(u)s= can only be set for relative time") % {"u": "unit"} - ) + msgr.fatal(_("unit can only be set for relative time")) if not isinstance(time_object, datetime) and not unit: - msgr.fatal( - _("%(u)s= must be set in case of relative time" " stamps") - % {"u": "unit"} - ) + msgr.fatal(_("unit must be set in case of relative time stamps")) if unit: - map.set_time_to_relative() + map_object.set_time_to_relative() else: - map.set_time_to_absolute() + map_object.set_time_to_absolute() else: - is_in_db = True # Check the overwrite flag - if not gscript.overwrite(): - if map.get_layer(): + if not overwrite: + if map_object_layer: msgr.warning( _( "Map is already registered in temporal " - "database. Unable to update %(t)s map " - "<%(id)s> with layer %(l)s. Overwrite flag" + "database. Unable to update {t} map " + "<{mid}> with layer {l}. Overwrite flag" " is not set." + ).format( + t=map_object_type, + mid=map_object_id, + l=str(map_object_layer), ) - % { - "t": map.get_type(), - "id": map.get_map_id(), - "l": str(map.get_layer()), - } ) else: msgr.warning( _( "Map is already registered in temporal " - "database. Unable to update %(t)s map " - "<%(id)s>. Overwrite flag is not set." - ) - % {"t": map.get_type(), "id": map.get_map_id()} + "database. Unable to update {t} map " + "<{mid}>. Overwrite flag is not set." + ).format(t=map_object_type, mid=map_object_id) ) # Simple registration is allowed if name: - map_object_list.append(map) + map_object_list.append(map_object) # Jump to next map continue - # Select information from temporal database - map.select(dbif) + # Reload properties from database + map_object.select(dbif) # Save the datasets that must be updated - datasets = map.get_registered_stds(dbif) + datasets = map_object.get_registered_stds(dbif) if datasets is not None: for dataset in datasets: if dataset != "": datatsets_to_modify[dataset] = dataset - if name and map.get_temporal_type() != sp.get_temporal_type(): + if name and map_object.get_temporal_type() != sp.get_temporal_type(): dbif.close() - if map.get_layer(): + if map_object_layer: msgr.fatal( _( - "Unable to update %(t)s map <%(id)s> " - "with layer %(l)s. The temporal types " + "Unable to update {t} map <{id}> " + "with layer {l}. The temporal types " "are different." + ).format( + t=map_object_type, + mid=map_object_id, + l=map_object_layer, ) - % { - "t": map.get_type(), - "id": map.get_map_id(), - "l": map.get_layer(), - } ) else: msgr.fatal( _( - "Unable to update %(t)s map <%(id)s>. " + "Unable to update {t} map <{mid}>. " "The temporal types are different." - ) - % {"t": map.get_type(), "id": map.get_map_id()} + ).format(t=map_object_type, mid=map_object_id) ) # Load the data from the grass file database - map.load() + map_object.load() # Try to read an existing time stamp from the grass spatial database # in case this map wasn't already registered in the temporal database # Read the spatial database time stamp only, if no time stamp was provided for this map # as method argument or in the input file if not is_in_db and not start: - map.read_timestamp_from_grass() + map_object.read_timestamp_from_grass() # Set the valid time if start: @@ -399,8 +385,8 @@ def register_maps_in_space_time_dataset( if start_time_in_file: count = 1 assign_valid_time_to_map( - ttype=map.get_temporal_type(), - map=map, + ttype=map_object.get_temporal_type(), + map_object=map_object, start=start, end=end, unit=unit, @@ -414,17 +400,17 @@ def register_maps_in_space_time_dataset( # semantic label defined in input file # -> update raster metadata # -> write band identifier to GRASS data base - map.set_semantic_label(semantic_label) + map_object.set_semantic_label(semantic_label) else: # Try to read semantic label from GRASS data base if defined - map.read_semantic_label_from_grass() + map_object.read_semantic_label_from_grass() if is_in_db: # Gather the SQL update statement - statement += map.update_all(dbif=dbif, execute=False) + statement += map_object.update_all(dbif=dbif, execute=False) else: # Gather the SQL insert statement - statement += map.insert(dbif=dbif, execute=False) + statement += map_object.insert(dbif=dbif, execute=False) # Sqlite3 performance is better for huge datasets when committing in # small chunks @@ -436,7 +422,7 @@ def register_maps_in_space_time_dataset( # Store the maps in a list to register in a space time dataset if name: - map_object_list.append(map) + map_object_list.append(map_object) msgr.percent(num_maps, num_maps, 1) @@ -445,13 +431,11 @@ def register_maps_in_space_time_dataset( # Finally Register the maps in the space time dataset if name and map_object_list: - count = 0 num_maps = len(map_object_list) - for map in map_object_list: + for count, map_object in enumerate(map_object_list): if count % 50 == 0: msgr.percent(count, num_maps, 1) - sp.register_map(map=map, dbif=dbif) - count += 1 + sp.register_map(map=map_object, dbif=dbif) # Update the space time tables if name and map_object_list: @@ -462,11 +446,11 @@ def register_maps_in_space_time_dataset( # Update affected datasets if datatsets_to_modify: for dataset in datatsets_to_modify: - if type == "rast" or type == "raster": + if type in ["rast", "raster"]: ds = dataset_factory("strds", dataset) - elif type == "raster_3d" or type == "rast3d" or type == "raster3d": + elif type in ["raster_3d", "rast3d", "raster3d"]: ds = dataset_factory("str3ds", dataset) - elif type == "vect" or type == "vector": + elif type in ["vect", "vector"]: ds = dataset_factory("stvds", dataset) ds.select(dbif) ds.update_from_registered_maps(dbif) @@ -481,7 +465,7 @@ def register_maps_in_space_time_dataset( def assign_valid_time_to_map( - ttype, map, start, end, unit, increment=None, mult=1, interval=False + ttype, map_object, start, end, unit, increment=None, mult=1, interval=False ): """Assign the valid time to a map dataset @@ -510,7 +494,7 @@ def assign_valid_time_to_map( start_time = string_to_datetime(start) if start_time is None: msgr.fatal( - _('Unable to convert string "%s"into a ' "datetime object") % (start) + _('Unable to convert string "{}" into a datetime object').format(start) ) end_time = None @@ -518,7 +502,9 @@ def assign_valid_time_to_map( end_time = string_to_datetime(end) if end_time is None: msgr.fatal( - _('Unable to convert string "%s"into a ' "datetime object") % (end) + _('Unable to convert string "{}" into a datetime object').format( + end + ) ) # Add the increment @@ -531,28 +517,32 @@ def assign_valid_time_to_map( if end_time is None: msgr.fatal(_("Error occurred in increment computation")) - if map.get_layer(): + if map_object.get_layer(): msgr.debug( 1, _( - "Set absolute valid time for map <%(id)s> with " - "layer %(layer)s to %(start)s - %(end)s" - ) - % { - "id": map.get_map_id(), - "layer": map.get_layer(), - "start": str(start_time), - "end": str(end_time), - }, + "Set absolute valid time for map <{id}> with " + "layer {layer} to {start} - {end}" + ).format( + id=map_object.get_map_id(), + layer=map_object.get_layer(), + start=str(start_time), + end=str(end_time), + ), ) else: msgr.debug( 1, - _("Set absolute valid time for map <%s> to %s - %s") - % (map.get_map_id(), str(start_time), str(end_time)), + _( + "Set absolute valid time for map <{mid}> to {start_time} - {end_time}" + ).format( + mid=map_object.get_map_id(), + start_time=str(start_time), + end_time=str(end_time), + ), ) - map.set_absolute_time(start_time, end_time) + map_object.set_absolute_time(start_time, end_time) else: start_time = int(start) end_time = None @@ -565,23 +555,34 @@ def assign_valid_time_to_map( if interval: end_time = start_time + int(increment) - if map.get_layer(): + if map_object.get_layer(): msgr.debug( 1, _( - "Set relative valid time for map <%s> with layer" - " %s to %i - %s with unit %s" - ) - % (map.get_map_id(), map.get_layer(), start_time, str(end_time), unit), + "Set relative valid time for map <{mid}> with layer" + " {layer} to {start} - {end} with unit {unit}" + ).format( + mid=map_object.get_map_id(), + layer=map_object.get_layer(), + start=start_time, + end=str(end_time), + unit=unit, + ), ) else: msgr.debug( 1, - _("Set relative valid time for map <%s> to %i - %s " "with unit %s") - % (map.get_map_id(), start_time, str(end_time), unit), + _( + "Set relative valid time for map <{mid}> to {start} - {end} with unit {unit}" + ).format( + mid=map_object.get_map_id(), + start=start_time, + end=str(end_time), + unit=unit, + ), ) - map.set_relative_time(start_time, end_time, unit) + map_object.set_relative_time(start_time, end_time, unit) ############################################################################## @@ -604,37 +605,34 @@ def register_map_object_list( import grass.pygrass.modules as pymod import copy - dbif, connection_state_changed = init_dbif(dbif) + dbif, connection_state_changed = init_dbif(None) - filename = gscript.tempfile(True) - file = open(filename, "w") - - empty_maps = [] - for map_layer in map_list: - # Read the map data - map_layer.load() - # In case of a empty map continue, do not register empty maps - - if delete_empty: - if type in ["raster", "raster_3d", "rast", "rast3d"]: - if ( - map_layer.metadata.get_min() is None - and map_layer.metadata.get_max() is None - ): - empty_maps.append(map_layer) - continue - if type == "vector": - if map_layer.metadata.get_number_of_primitives() == 0: - empty_maps.append(map_layer) - continue - - start, end = map_layer.get_temporal_extent_as_tuple() - id = map_layer.get_id() - if not end: - end = start - string = "%s|%s|%s\n" % (id, str(start), str(end)) - file.write(string) - file.close() + filename = gs.tempfile(True) + with open(filename, "w") as register_file: + empty_maps = [] + for map_layer in map_list: + # Read the map data + map_layer.load() + # In case of a empty map continue, do not register empty maps + if delete_empty: + if type in ["raster", "raster_3d", "rast", "rast3d"]: + if ( + map_layer.metadata.get_min() is None + and map_layer.metadata.get_max() is None + ): + empty_maps.append(map_layer) + continue + if type == "vector": + if map_layer.metadata.get_number_of_primitives() == 0: + empty_maps.append(map_layer) + continue + + start, end = map_layer.get_temporal_extent_as_tuple() + id = map_layer.get_id() + if not end: + end = start + string = f"{id}|{start}|{end}\n" + register_file.write(string) if output_stds: output_stds_id = output_stds.get_id() @@ -645,22 +643,21 @@ def register_map_object_list( type, output_stds_id, unit=unit, file=filename, dbif=dbif ) - g_remove = pymod.Module("g.remove", flags="f", quiet=True, run_=False, finish_=True) - # Remove empty maps and unregister them from the temporal database + g_remove = pymod.Module("g.remove", flags="f", quiet=True, run_=False, finish_=True) if len(empty_maps) > 0: - for map in empty_maps: + for map_object in empty_maps: mod = copy.deepcopy(g_remove) - if map.get_name(): - if map.get_type() == "raster": - mod(type="raster", name=map.get_name()) - if map.get_type() == "raster3d": - mod(type="raster_3d", name=map.get_name()) - if map.get_type() == "vector": - mod(type="vector", name=map.get_name()) + if map_object.get_name(): + if map_object.get_type() == "raster": + mod(type="raster", name=map_object.get_name()) + if map_object.get_type() == "raster3d": + mod(type="raster_3d", name=map_object.get_name()) + if map_object.get_type() == "vector": + mod(type="vector", name=map_object.get_name()) mod.run() - if map.is_in_db(dbif): - map.delete(dbif) + if map_object.is_in_db(dbif): + map_object.delete(dbif) if connection_state_changed: dbif.close() diff --git a/python/grass/temporal/space_time_datasets.py b/python/grass/temporal/space_time_datasets.py index 372f32900a1..c6acca67358 100644 --- a/python/grass/temporal/space_time_datasets.py +++ b/python/grass/temporal/space_time_datasets.py @@ -10,6 +10,7 @@ """ import getpass +from datetime import datetime from .abstract_map_dataset import AbstractMapDataset from .abstract_space_time_dataset import AbstractSpaceTimeDataset from .base import ( @@ -56,6 +57,8 @@ import grass.script.array as garray +GRASS_TIMESTAMP_FMT = "%a %b %d %H:%M:%S %Y" + ############################################################################### @@ -409,7 +412,16 @@ def load(self): return False # Fill base information - self.base.set_creator(str(getpass.getuser())) + kvp = self.ciface.read_raster_history(self.get_name(), self.get_mapset()) + + if kvp: + self.base.set_creator(kvp["creator"]) + self.base.set_ctime( + datetime.strptime(kvp["creation_time"], GRASS_TIMESTAMP_FMT) + ) + else: + self.base.set_creator(str(getpass.getuser())) + self.base.set_ctime() kvp = self.ciface.read_raster_info(self.get_name(), self.get_mapset()) @@ -791,7 +803,16 @@ def load(self): return False # Fill base information - self.base.set_creator(str(getpass.getuser())) + kvp = self.ciface.read_raster3d_history(self.get_name(), self.get_mapset()) + + if kvp: + self.base.set_creator(kvp["creator"]) + self.base.set_ctime( + datetime.strptime(kvp["creation_time"], GRASS_TIMESTAMP_FMT) + ) + else: + self.base.set_creator(str(getpass.getuser())) + self.base.set_ctime() # Fill spatial extent kvp = self.ciface.read_raster3d_info(self.get_name(), self.get_mapset()) @@ -1115,10 +1136,18 @@ def load(self): return False # Fill base information - self.base.set_creator(str(getpass.getuser())) + kvp = self.ciface.read_vector_history(self.get_name(), self.get_mapset()) - # Get the data from an existing vector map + if kvp: + self.base.set_creator(kvp["creator"]) + self.base.set_ctime( + datetime.strptime(kvp["creation_time"], GRASS_TIMESTAMP_FMT) + ) + else: + self.base.set_creator(str(getpass.getuser())) + self.base.set_ctime() + # Get the data from an existing vector map kvp = self.ciface.read_vector_info(self.get_name(), self.get_mapset()) if kvp: diff --git a/python/grass/temporal/testsuite/test_register_function.py b/python/grass/temporal/testsuite/test_register_function.py index fcf1ad756bf..923e4034027 100644 --- a/python/grass/temporal/testsuite/test_register_function.py +++ b/python/grass/temporal/testsuite/test_register_function.py @@ -24,7 +24,7 @@ def setUpClass(cls): os.putenv("GRASS_OVERWRITE", "1") # Use always the current mapset as temporal database cls.runModule("g.gisenv", set="TGIS_USE_CURRENT_MAPSET=1") - tgis.init() + cls.dbif = tgis.init() cls.use_temp_region() cls.runModule("g.region", n=80.0, s=0.0, e=120.0, w=0.0, t=1.0, b=0.0, res=10.0) @@ -72,7 +72,7 @@ def tearDown(self): self.runModule( "t.unregister", type="raster", - maps="register_map_1,register_map_2", + maps="register_map_1,register_map_2,elevation", quiet=True, ) self.runModule( @@ -118,7 +118,8 @@ def test_absolute_time_strds_1(self): def test_absolute_time_strds_2(self): """Test the registration of maps with absolute time in a space time raster dataset. - The timestamps are set using the C-Interface beforehand, so that the register function needs + The timestamps are set using the C-Interface beforehand, + so that the register function needs to read the timetsamp from the map metadata. """ @@ -155,9 +156,10 @@ def test_absolute_time_strds_2(self): def test_absolute_time_strds_3(self): """Test the registration of maps with absolute time in a - space time raster dataset. The timestamps are set via method arguments and with the - c-interface. The timestamps of the method arguments should overwrite the - time stamps set via the C-interface. + space time raster dataset. The timestamps are set via method + arguments and with the c-interface. The timestamps of the + method arguments should overwrite the time stamps set via the + C-interface. """ ciface = tgis.get_tgis_c_library_interface() @@ -187,9 +189,10 @@ def test_absolute_time_strds_3(self): def test_absolute_time_strds_4(self): """Test the registration of maps with absolute time in a - space time raster dataset. The timestamps are set via method arguments and with the - c-interface. The timestamps of the method arguments should overwrite the - time stamps set via the C-interface. The C-interface sets relative time stamps. + space time raster dataset. The timestamps are set via method + arguments and with the c-interface. The timestamps of the method + arguments should overwrite the time stamps set via the C-interface. + The C-interface sets relative time stamps. """ ciface = tgis.get_tgis_c_library_interface() @@ -258,7 +261,8 @@ def test_absolute_time_1(self): def test_absolute_time_2(self): """Test the registration of maps with absolute time - using register_maps_in_space_time_dataset() and register_map_object_list() with empty map deletion + using register_maps_in_space_time_dataset() and + register_map_object_list() with empty map deletion """ tgis.register_maps_in_space_time_dataset( type="raster", @@ -300,9 +304,58 @@ def test_absolute_time_2(self): map_3 = tgis.VectorDataset("register_map_null@" + tgis.get_current_mapset()) self.assertEqual(map_3.map_exists(), False) + def test_history_raster(self): + """Test that raster maps are registered with the history + (creator and creation time) of the raster map itself (and from a + different mapset (PERMANENT) + """ + tgis.register_maps_in_space_time_dataset( + type="raster", + name=None, + maps="elevation@PERMANENT", + start="2001-01-01 10:30:01", + increment="1 year", + interval=True, + dbif=self.dbif, + ) + + map_1 = tgis.RasterDataset("elevation@PERMANENT") + map_1.select(self.dbif, tgis.get_current_mapset()) + # Test that creation time of the map is used + self.assertEqual( + map_1.base.get_ctime(), datetime.datetime(2006, 11, 7, 1, 9, 51) + ) + # Test that registered creator of the map is not the current user + self.assertEqual(map_1.base.get_creator(), "helena") + + def test_history_vector(self): + """Test that vector maps are registered with the history (creator + and creation time) of the vector map itself (and from a + different mapset (PERMANENT) + """ + tgis.register_maps_in_space_time_dataset( + type="vector", + name=None, + maps="lakes@PERMANENT", + start="2001-01-01 10:30:01", + increment="1 year", + interval=True, + dbif=self.dbif, + ) + + map_1 = tgis.VectorDataset("lakes@PERMANENT") + map_1.select(self.dbif, tgis.get_current_mapset()) + # Test that creation time of the map is used + self.assertEqual( + map_1.base.get_ctime(), datetime.datetime(2006, 11, 7, 19, 48, 8) + ) + # Test that registered creator of the map is not the current user + self.assertTrue(map_1.base.get_creator(), "helena") + def test_absolute_time_3(self): """Test the registration of maps with absolute time. - The timestamps are set using the C-Interface beforehand, so that the register function needs + The timestamps are set using the C-Interface beforehand, + so that the register function needs to read the timetsamp from the map metadata. """ @@ -365,8 +418,8 @@ def test_relative_time_strds_1(self): def test_relative_time_strds_2(self): """Test the registration of maps with relative time in a - space time raster dataset. The timetsamps are set for the maps using the - C-interface before registration. + space time raster dataset. The timestamps are set for the maps + using the C-interface before registration. """ ciface = tgis.get_tgis_c_library_interface() ciface.write_raster_timestamp( @@ -459,8 +512,8 @@ def test_relative_time_2(self): self.assertEqual(unit, "seconds") def test_relative_time_3(self): - """Test the registration of maps with relative time. The timetsamps are set beforehand using - the C-interface. + """Test the registration of maps with relative time. The + timestamps are set beforehand using the C-interface. """ ciface = tgis.get_tgis_c_library_interface() ciface.write_raster_timestamp( @@ -619,7 +672,8 @@ def test_absolute_time_stvds_1(self): def test_absolute_time_stvds_2(self): """Test the registration of maps with absolute time in a space time raster dataset. - The timestamps are set using the C-Interface beforehand, so that the register function needs + The timestamps are set using the C-Interface beforehand, + so that the register function needs to read the timetsamp from the map metadata. """ @@ -656,9 +710,9 @@ def test_absolute_time_stvds_2(self): def test_absolute_time_stvds_3(self): """Test the registration of maps with absolute time in a - space time raster dataset. The timestamps are set via method arguments and with the - c-interface. The timestamps of the method arguments should overwrite the - time stamps set via the C-interface. + space time raster dataset. The timestamps are set via method + arguments and with the C-interface. The timestamps of the method + arguments should overwrite the time stamps set via the C-interface. """ ciface = tgis.get_tgis_c_library_interface() @@ -687,7 +741,8 @@ def test_absolute_time_stvds_3(self): self.assertEqual(end, datetime.datetime(2001, 2, 2)) def test_absolute_time_1(self): - """Register vector maps in the temporal database and in addition in a stvds using the object method + """Register vector maps in the temporal database and in addition + in a stvds using the object method :return: """ From 2c3e94c84ab9901759e8eaafb77f1b8164a5b680 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 24 Apr 2024 06:45:41 -0400 Subject: [PATCH 21/27] CI(deps): Update debian:stable Docker digest to 84725fb (#3658) --- docker/debian/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/debian/Dockerfile b/docker/debian/Dockerfile index 776b8c5a1d4..c15299386cd 100644 --- a/docker/debian/Dockerfile +++ b/docker/debian/Dockerfile @@ -1,4 +1,4 @@ -FROM debian:stable@sha256:fef26aa981ff8c3eeb09b20555ec6e02b38e6b227ec0b88bef7fde778cbf848a +FROM debian:stable@sha256:84725fb1debbf461f54a23030be0bcde8449f2fa4eba8adf857b1a4c707fec8d # currently Debian 12 # docker run -it --rm debian:stable bash From 14d272a951f1bf1b8c014158d18fa387351f4cbb Mon Sep 17 00:00:00 2001 From: Veronica Andreo Date: Wed, 24 Apr 2024 08:35:11 -0400 Subject: [PATCH 22/27] Update bug report template (#3657) --- .github/ISSUE_TEMPLATE/bug_report.md | 31 ++++++++++++++-------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 144b415cb39..57ad644c0b9 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -7,36 +7,35 @@ assignees: '' --- -**Describe the bug** -A clear and concise description of what the bug is. +## Describe the bug + -**To Reproduce** -Steps to reproduce the behavior: +## To reproduce + -**Expected behavior** -A clear and concise description of what you expected to happen. +## Expected behavior + -**Screenshots** -If applicable, add screenshots to help explain your problem. - -**System description (please complete the following information):** +## Screenshots + +## System description + +--> -**Additional context** -Add any other context about the problem here. +## Additional context + From e358df7cb1344e9d99c748ec9a8a534a9a12fe6c Mon Sep 17 00:00:00 2001 From: Anna Petrasova Date: Wed, 24 Apr 2024 09:32:21 -0400 Subject: [PATCH 23/27] doc: renaming location to project continued (#3627) --- general/g.mapsets/tests/conftest.py | 2 +- raster/r.external/main.c | 7 ++--- raster/r.external/proj.c | 45 +++++++++++++++-------------- raster/r.in.lidar/main.c | 7 +++-- raster/r.in.lidar/projection.c | 17 ++++++----- raster/r.in.lidar/r.in.lidar.html | 2 +- raster/r.in.pdal/main.cpp | 17 ++++++----- raster/r.in.pdal/projection.c | 16 +++++----- raster/r.in.pdal/r.in.pdal.html | 2 +- raster3d/r3.in.lidar/main.c | 7 +++-- raster3d/r3.in.lidar/projection.c | 17 ++++++----- scripts/r.unpack/r.unpack.py | 21 +++++++------- scripts/v.import/v.import.html | 40 ------------------------- scripts/v.unpack/v.unpack.py | 17 ++++++----- vector/v.external/args.c | 7 +++-- vector/v.external/proj.c | 44 ++++++++++++++-------------- vector/v.in.lidar/main.c | 27 ++++++++--------- vector/v.in.lidar/projection.c | 17 ++++++----- vector/v.in.lidar/v.in.lidar.html | 4 +-- vector/v.in.pdal/main.cpp | 17 ++++++----- vector/v.in.pdal/projection.c | 16 +++++----- 21 files changed, 161 insertions(+), 188 deletions(-) diff --git a/general/g.mapsets/tests/conftest.py b/general/g.mapsets/tests/conftest.py index ae4f1c106f9..58986369c03 100644 --- a/general/g.mapsets/tests/conftest.py +++ b/general/g.mapsets/tests/conftest.py @@ -27,7 +27,7 @@ def simple_dataset(tmp_path_factory): gs.run_command("g.region", s=0, n=80, w=0, e=120, b=0, t=50, res=10, res3=10) # Create Mock Mapsets for mapset in TEST_MAPSETS: - gs.run_command("g.mapset", location=location, mapset=mapset, flags="c") + gs.run_command("g.mapset", project=location, mapset=mapset, flags="c") yield SimpleNamespace( mapsets=TEST_MAPSETS, accessible_mapsets=ACCESSIBLE_MAPSETS diff --git a/raster/r.external/main.c b/raster/r.external/main.c index c3ee9b8daf2..baf5b7c8ea0 100644 --- a/raster/r.external/main.c +++ b/raster/r.external/main.c @@ -98,10 +98,9 @@ int main(int argc, char *argv[]) flag.o = G_define_flag(); flag.o->key = 'o'; - flag.o->label = - _("Override projection check (use current location's projection)"); - flag.o->description = _( - "Assume that the dataset has same projection as the current location"); + flag.o->label = _("Override projection check (use current project's CRS)"); + flag.o->description = _("Assume that the dataset has the same coordinate " + "reference system as the current project"); flag.j = G_define_flag(); flag.j->key = 'j'; diff --git a/raster/r.external/proj.c b/raster/r.external/proj.c index 0e38578fe06..7b9b8043133 100644 --- a/raster/r.external/proj.c +++ b/raster/r.external/proj.c @@ -130,15 +130,16 @@ void check_projection(struct Cell_head *cellhd, GDALDatasetH hDS, char *outloc, if (outloc != NULL) { /* do not create a xy location if an existing SRS was unreadable */ if (proj_trouble == 2) { - G_fatal_error(_("Unable to convert input map projection to GRASS " - "format; cannot create new location.")); + G_fatal_error( + _("Unable to convert input map coordinate reference " + "system to GRASS format; cannot create new project.")); } else { if (0 != G_make_location_crs(outloc, cellhd, proj_info, proj_units, srid, wkt)) { - G_fatal_error(_("Unable to create new location <%s>"), outloc); + G_fatal_error(_("Unable to create new project <%s>"), outloc); } - G_message(_("Location <%s> created"), outloc); + G_message(_("Project <%s> created"), outloc); G_unset_window(); /* new location, projection, and window */ G_get_window(cellhd); @@ -195,14 +196,15 @@ void check_projection(struct Cell_head *cellhd, GDALDatasetH hDS, char *outloc, proj_info, proj_units)) != 1) { int i_value; - strcpy(error_msg, _("Projection of dataset does not" - " appear to match current location.\n\n")); + strcpy(error_msg, + _("Coordinate reference system of dataset does not" + " appear to match current project.\n\n")); /* TODO: output this info sorted by key: */ if (loc_wind.proj != cellhd->proj || err != -2) { /* error in proj_info */ if (loc_proj_info != NULL) { - strcat(error_msg, _("Location PROJ_INFO is:\n")); + strcat(error_msg, _("Project PROJ_INFO is:\n")); for (i_value = 0; i_value < loc_proj_info->nitems; i_value++) sprintf(error_msg + strlen(error_msg), "%s: %s\n", @@ -211,22 +213,22 @@ void check_projection(struct Cell_head *cellhd, GDALDatasetH hDS, char *outloc, strcat(error_msg, "\n"); } else { - strcat(error_msg, _("Location PROJ_INFO is:\n")); + strcat(error_msg, _("Project PROJ_INFO is:\n")); if (loc_wind.proj == PROJECTION_XY) sprintf(error_msg + strlen(error_msg), - "Location proj = %d (unreferenced/unknown)\n", + "Project proj = %d (unreferenced/unknown)\n", loc_wind.proj); else if (loc_wind.proj == PROJECTION_LL) sprintf(error_msg + strlen(error_msg), - "Location proj = %d (lat/long)\n", + "Project proj = %d (lat/long)\n", loc_wind.proj); else if (loc_wind.proj == PROJECTION_UTM) sprintf(error_msg + strlen(error_msg), - "Location proj = %d (UTM), zone = %d\n", + "Project proj = %d (UTM), zone = %d\n", loc_wind.proj, cellhd->zone); else sprintf(error_msg + strlen(error_msg), - "Location proj = %d (unknown), zone = %d\n", + "Project proj = %d (unknown), zone = %d\n", loc_wind.proj, cellhd->zone); } @@ -300,7 +302,7 @@ void check_projection(struct Cell_head *cellhd, GDALDatasetH hDS, char *outloc, else { /* error in proj_units */ if (loc_proj_units != NULL) { - strcat(error_msg, "Location PROJ_UNITS is:\n"); + strcat(error_msg, "Project PROJ_UNITS is:\n"); for (i_value = 0; i_value < loc_proj_units->nitems; i_value++) sprintf(error_msg + strlen(error_msg), "%s: %s\n", @@ -318,13 +320,14 @@ void check_projection(struct Cell_head *cellhd, GDALDatasetH hDS, char *outloc, } } if (!check_only) { - strcat(error_msg, _("\nIn case of no significant differences " - "in the projection definitions," - " use the -o flag to ignore them and use" - " current location definition.\n")); - strcat(error_msg, _("Consider generating a new location from " + strcat(error_msg, + _("\nIn case of no significant differences " + "in the coordinate reference system definitions," + " use the -o flag to ignore them and use" + " current project definition.\n")); + strcat(error_msg, _("Consider generating a new project from " "the input dataset using " - "the 'location' parameter.\n")); + "the 'project' parameter.\n")); } if (check_only) @@ -342,8 +345,8 @@ void check_projection(struct Cell_head *cellhd, GDALDatasetH hDS, char *outloc, msg_fn = G_message; else msg_fn = G_verbose_message; - msg_fn(_("Projection of input dataset and current location " - "appear to match")); + msg_fn(_("Coordinate reference system of input dataset and current " + "project appear to match")); if (check_only) { GDALClose(hDS); exit(EXIT_SUCCESS); diff --git a/raster/r.in.lidar/main.c b/raster/r.in.lidar/main.c index 9c7d4cdad8f..68d3a0fcd1b 100644 --- a/raster/r.in.lidar/main.c +++ b/raster/r.in.lidar/main.c @@ -300,9 +300,10 @@ int main(int argc, char *argv[]) over_flag = G_define_flag(); over_flag->key = 'o'; over_flag->label = - _("Override projection check (use current location's projection)"); - over_flag->description = _( - "Assume that the dataset has same projection as the current location"); + _("Override projection check (use current project's CRS)"); + over_flag->description = + _("Assume that the dataset has the same coordinate reference system as " + "the current project"); scan_flag = G_define_flag(); scan_flag->key = 's'; diff --git a/raster/r.in.lidar/projection.c b/raster/r.in.lidar/projection.c index faf123db11b..a3c4ff057b2 100644 --- a/raster/r.in.lidar/projection.c +++ b/raster/r.in.lidar/projection.c @@ -29,8 +29,8 @@ void projection_mismatch_report(struct Cell_head cellhd, int i_value; char error_msg[8192]; - strcpy(error_msg, _("Projection of dataset does not" - " appear to match current location.\n\n")); + strcpy(error_msg, _("Coordinate reference system of dataset does not" + " appear to match current project.\n\n")); /* TODO: output this info sorted by key: */ if (loc_wind.proj != cellhd.proj || err != -2) { @@ -86,12 +86,12 @@ void projection_mismatch_report(struct Cell_head cellhd, } } sprintf(error_msg + strlen(error_msg), - _("\nIn case of no significant differences in the projection " - "definitions," + _("\nIn case of no significant differences" + " in the coordinate reference system definitions," " use the -o flag to ignore them and use" - " current location definition.\n")); + " current project definition.\n")); strcat(error_msg, - _("Consider generating a new location with 'location' parameter" + _("Consider generating a new project with 'project' parameter" " from input data set.\n")); G_fatal_error("%s", error_msg); } @@ -132,7 +132,8 @@ void projection_check_wkt(struct Cell_head cellhd, struct Cell_head loc_wind, loc_proj_units, proj_info, proj_units, err); } else if (verbose) { - G_message(_("Projection of input dataset and current location " - "appear to match")); + G_message(_( + "Coordinate reference system of input dataset and current project " + "appear to match")); } } diff --git a/raster/r.in.lidar/r.in.lidar.html b/raster/r.in.lidar/r.in.lidar.html index ff32c8291c2..6cff187c089 100644 --- a/raster/r.in.lidar/r.in.lidar.html +++ b/raster/r.in.lidar/r.in.lidar.html @@ -464,7 +464,7 @@

Serpent Mound dataset

# using v.in.lidar to create a new project # create project with CRS information of the LAS data -v.in.lidar -i input="Serpent Mound Model LAS Data.las" location=Serpent_Mound +v.in.lidar -i input="Serpent Mound Model LAS Data.las" project=Serpent_Mound # quit and restart GRASS in the newly created project "Serpent_Mound" diff --git a/raster/r.in.pdal/main.cpp b/raster/r.in.pdal/main.cpp index 63ab5c19f03..093b17258e1 100644 --- a/raster/r.in.pdal/main.cpp +++ b/raster/r.in.pdal/main.cpp @@ -248,10 +248,10 @@ int main(int argc, char *argv[]) reproject_flag->key = 'w'; reproject_flag->label = - _("Reproject to location's coordinate system if needed"); + _("Reproject to project's coordinate system if needed"); reproject_flag->description = _("Reprojects input dataset to the coordinate system of" - " the GRASS location (by default only datasets with the" + " the GRASS project (by default only datasets with" " matching coordinate system can be imported"); reproject_flag->guisection = _("Projection"); @@ -393,9 +393,10 @@ int main(int argc, char *argv[]) over_flag->key = 'o'; over_flag->label = - _("Override projection check (use current location's projection)"); - over_flag->description = _( - "Assume that the dataset has same projection as the current location"); + _("Override projection check (use current project's CRS)"); + over_flag->description = + _("Assume that the dataset has the same coordinate reference system as " + "the current project"); over_flag->guisection = _("Projection"); Flag *base_rast_res_flag = G_define_flag(); @@ -731,7 +732,7 @@ int main(int argc, char *argv[]) // we reproject when requested regardless of the input projection if (reproject_flag->answer) { - G_message(_("Reprojecting the input to the location projection")); + G_message(_("Reprojecting the input to the project's CRS")); char *proj_wkt = location_projection_as_wkt(false); pdal::Options o4; @@ -781,8 +782,8 @@ int main(int argc, char *argv[]) // getting projection is possible only after prepare if (over_flag->answer) { G_important_message(_("Overriding projection check and assuming" - " that the projection of input matches" - " the location projection")); + " that the CRS of input matches" + " the project's CRS")); } else if (!reproject_flag->answer) { pdal::SpatialReference spatial_reference = diff --git a/raster/r.in.pdal/projection.c b/raster/r.in.pdal/projection.c index 244ee323afb..25e6da8e25e 100644 --- a/raster/r.in.pdal/projection.c +++ b/raster/r.in.pdal/projection.c @@ -27,8 +27,8 @@ void projection_mismatch_report(struct Cell_head cellhd, int i_value; char error_msg[8192]; - strcpy(error_msg, _("Projection of dataset does not" - " appear to match current location.\n\n")); + strcpy(error_msg, _("Coordinate reference system of dataset does not" + " appear to match current project.\n\n")); /* TODO: output this info sorted by key: */ if (loc_wind.proj != cellhd.proj || err != -2) { @@ -84,12 +84,12 @@ void projection_mismatch_report(struct Cell_head cellhd, } } sprintf(error_msg + strlen(error_msg), - _("\nIn case of no significant differences in the projection " - "definitions," + _("\nIn case of no significant differences" + " in the coordinate reference system definitions," " use the -o flag to ignore them and use" - " current location definition.\n")); + " current project definition.\n")); strcat(error_msg, - _("Consider generating a new location with 'location' parameter" + _("Consider generating a new project with 'project' parameter" " from input data set.\n")); G_fatal_error("%s", error_msg); } @@ -131,8 +131,8 @@ void projection_check_wkt(struct Cell_head cellhd, struct Cell_head loc_wind, } else { if (verbose) { - G_message(_("Projection of input dataset and current location " - "appear to match")); + G_message(_("Coordinate reference system of input dataset and " + "current project appear to match")); } } } diff --git a/raster/r.in.pdal/r.in.pdal.html b/raster/r.in.pdal/r.in.pdal.html index 3dd9d068ac7..92cd25205e8 100644 --- a/raster/r.in.pdal/r.in.pdal.html +++ b/raster/r.in.pdal/r.in.pdal.html @@ -522,7 +522,7 @@

Serpent Mound dataset

# using v.in.lidar to create a new project # create a project with CRS information of the LAS data -v.in.lidar -i input="Serpent Mound Model LAS Data.las" location=Serpent_Mound +v.in.lidar -i input="Serpent Mound Model LAS Data.las" project=Serpent_Mound # quit and restart GRASS in the newly created project "Serpent_Mound" diff --git a/raster3d/r3.in.lidar/main.c b/raster3d/r3.in.lidar/main.c index cd622a6098f..6170a3f50ba 100644 --- a/raster3d/r3.in.lidar/main.c +++ b/raster3d/r3.in.lidar/main.c @@ -287,9 +287,10 @@ int main(int argc, char *argv[]) over_flag = G_define_flag(); over_flag->key = 'o'; over_flag->label = - _("Override projection check (use current location's projection)"); - over_flag->description = _( - "Assume that the dataset has same projection as the current location"); + _("Override projection check (use current projects's CRS)"); + over_flag->description = + _("Assume that the dataset has the same coordinate " + "reference system as the current project"); print_flag = G_define_flag(); print_flag->key = 'p'; diff --git a/raster3d/r3.in.lidar/projection.c b/raster3d/r3.in.lidar/projection.c index 40eb4b6e289..a3ebea5d7f4 100644 --- a/raster3d/r3.in.lidar/projection.c +++ b/raster3d/r3.in.lidar/projection.c @@ -30,8 +30,8 @@ void projection_mismatch_report(struct Cell_head cellhd, int i_value; char error_msg[8192]; - strcpy(error_msg, _("Projection of dataset does not" - " appear to match current location.\n\n")); + strcpy(error_msg, _("Coordinate reference system of dataset does not" + " appear to match current project.\n\n")); /* TODO: output this info sorted by key: */ if (loc_wind.proj != cellhd.proj || err != -2) { @@ -87,12 +87,12 @@ void projection_mismatch_report(struct Cell_head cellhd, } } sprintf(error_msg + strlen(error_msg), - _("\nIn case of no significant differences in the projection " - "definitions," + _("\nIn case of no significant differences in the" + " coordinate reference system definitions," " use the -o flag to ignore them and use" - " current location definition.\n")); + " current project definition.\n")); strcat(error_msg, - _("Consider generating a new location with 'location' parameter" + _("Consider generating a new project with 'project' parameter" " from input data set.\n")); G_fatal_error("%s", error_msg); } @@ -133,7 +133,8 @@ void projection_check_wkt(struct Cell_head cellhd, struct Cell_head loc_wind, loc_proj_units, proj_info, proj_units, err); } else if (verbose) { - G_message(_("Projection of input dataset and current location " - "appear to match")); + G_message(_( + "Coordinate reference system of input dataset and current project " + "appear to match")); } } diff --git a/scripts/r.unpack/r.unpack.py b/scripts/r.unpack/r.unpack.py index 8ec8cdcba48..63b66ad65d9 100644 --- a/scripts/r.unpack/r.unpack.py +++ b/scripts/r.unpack/r.unpack.py @@ -30,8 +30,8 @@ # %end # %flag # % key: o -# % label: Override projection check (use current location's projection) -# % description: Assume that the dataset has same projection as the current location +# % label: Override projection check (use current projects's CRS) +# % description: Assume that the dataset has same coordinate reference system as the current project # % guisection: Output settings # %end # %flag @@ -140,9 +140,7 @@ def main(): # check projection compatibility in a rather crappy way if flags["o"]: - grass.warning( - _("Overriding projection check (using current location's projection).") - ) + grass.warning(_("Overriding projection check (using current project's CRS).")) else: diff_result_1 = diff_result_2 = None @@ -155,7 +153,7 @@ def main(): if os.path.exists(proj_info_file_2): grass.fatal( _( - "PROJ_INFO file is missing, unpack raster map in XY (unprojected) location." + "PROJ_INFO file is missing, unpack raster map in XY (unprojected) project." ) ) skip_projection_check = True # XY location @@ -179,22 +177,23 @@ def main(): grass.warning( _( "Difference between PROJ_INFO file of packed map " - "and of current location:\n{diff}" + "and of current project:\n{diff}" ).format(diff="".join(diff_result_1)) ) if diff_result_2: grass.warning( _( "Difference between PROJ_UNITS file of packed map " - "and of current location:\n{diff}" + "and of current project:\n{diff}" ).format(diff="".join(diff_result_2)) ) grass.fatal( _( - "Projection of dataset does not appear to match current location." - " In case of no significant differences in the projection definitions," + "Coordinate reference system of dataset does" + " not appear to match current project." + " In case of no significant differences in the CRS definitions," " use the -o flag to ignore them and use" - " current location definition." + " current project definition." ) ) diff --git a/scripts/v.import/v.import.html b/scripts/v.import/v.import.html index 072b92e5529..a530f5f3662 100644 --- a/scripts/v.import/v.import.html +++ b/scripts/v.import/v.import.html @@ -64,46 +64,6 @@

EXAMPLE

v.import input=research_area.shp output=research_area extent=input -

ERROR MESSAGES

- -

SQL syntax errors

- -Depending on the currently selected SQL driver, error messages such as follows may arise: - -
-DBMI-SQLite driver error:
-Error in sqlite3_prepare():
-near "ORDER": syntax error
-
- -Or: - -
-DBMI-DBF driver error:
-SQL parser error:
-syntax error, unexpected DESC, expecting NAME processing 'DESC
-
- -This indicates that a column name in the input dataset corresponds to a reserved -SQL word (here: 'ORDER' and 'DESC' respectively). A different column name has to be -used in this case. The columns parameter can be used to assign different -column names on the fly in order to avoid using reserved SQL words. - -For a list of SQL reserved words for SQLite (the default driver), -see here. - -

Projection errors

- -
-Projection of dataset does not appear to match the current project.
-
- -Here you need to create or use a project whose CRS matches that -of the vector data you wish to import. Try using location parameter to -create a new project based upon the CRS information in the file. If -desired, you can then re-project it to another project -with v.proj. -

SEE ALSO

diff --git a/scripts/v.unpack/v.unpack.py b/scripts/v.unpack/v.unpack.py index c55432316ce..04070770ec9 100644 --- a/scripts/v.unpack/v.unpack.py +++ b/scripts/v.unpack/v.unpack.py @@ -32,8 +32,8 @@ # %end # %flag # % key: o -# % label: Override projection check (use current location's projection) -# % description: Assume that the dataset has same projection as the current location +# % label: Override projection check (use current projects's CRS) +# % description: Assume that the dataset has same coordinate reference system as the current project # % guisection: Output settings # %end # %flag @@ -154,7 +154,7 @@ def main(): if os.path.exists(loc_proj): grass.fatal( _( - "PROJ_INFO file is missing, unpack vector map in XY (unprojected) location." + "PROJ_INFO file is missing, unpack vector map in XY (unprojected) project." ) ) skip_projection_check = True # XY location @@ -185,22 +185,23 @@ def main(): grass.warning( _( "Difference between PROJ_INFO file of packed map " - "and of current location:\n{diff}" + "and of current project:\n{diff}" ).format(diff="".join(diff_result_1)) ) if diff_result_2: grass.warning( _( "Difference between PROJ_UNITS file of packed map " - "and of current location:\n{diff}" + "and of current project:\n{diff}" ).format(diff="".join(diff_result_2)) ) grass.fatal( _( - "Projection of dataset does not appear to match current location." - " In case of no significant differences in the projection definitions," + "Coordinate reference system of dataset does not" + " appear to match current project." + " In case of no significant differences in the CRS definitions," " use the -o flag to ignore them and use" - " current location definition." + " current project definition." ) ) diff --git a/vector/v.external/args.c b/vector/v.external/args.c index 798982f2c15..7f482f836e6 100644 --- a/vector/v.external/args.c +++ b/vector/v.external/args.c @@ -46,9 +46,10 @@ void parse_args(int argc, char **argv, struct _options *options, flags->override = G_define_flag(); flags->override->key = 'o'; flags->override->label = - _("Override projection check (use current location's projection)"); - flags->override->description = _("Assume that the dataset has the same " - "projection as the current location"); + _("Override projection check (use current project's CRS)"); + flags->override->description = + _("Assume that the dataset has the same " + "coordinate reference system as the current project"); flags->proj = G_define_flag(); flags->proj->key = 'j'; diff --git a/vector/v.external/proj.c b/vector/v.external/proj.c index b1eae407c35..625482fee5e 100644 --- a/vector/v.external/proj.c +++ b/vector/v.external/proj.c @@ -163,15 +163,15 @@ void check_projection(struct Cell_head *cellhd, GDALDatasetH hDS, int layer, /* do not create a xy location because this can mean that the * real SRS has not been recognized or is missing */ if (proj_trouble) { - G_fatal_error(_("Unable to convert input map projection to GRASS " - "format; cannot create new location.")); + G_fatal_error(_("Unable to convert input map CRS to GRASS " + "format; cannot create new project.")); } else { if (0 != G_make_location_crs(outloc, cellhd, proj_info, proj_units, srid, wkt)) { - G_fatal_error(_("Unable to create new location <%s>"), outloc); + G_fatal_error(_("Unable to create new project <%s>"), outloc); } - G_message(_("Location <%s> created"), outloc); + G_message(_("Project <%s> created"), outloc); G_unset_window(); /* new location, projection, and window */ G_get_window(cellhd); @@ -232,14 +232,15 @@ void check_projection(struct Cell_head *cellhd, GDALDatasetH hDS, int layer, proj_info, proj_units)) != 1) { int i_value; - strcpy(error_msg, _("Projection of dataset does not" - " appear to match current location.\n\n")); + strcpy(error_msg, + _("Coordinate reference system of dataset does not" + " appear to match current project.\n\n")); /* TODO: output this info sorted by key: */ if (loc_wind.proj != cellhd->proj || err != -2) { /* error in proj_info */ if (loc_proj_info != NULL) { - strcat(error_msg, _("Location PROJ_INFO is:\n")); + strcat(error_msg, _("Project PROJ_INFO is:\n")); for (i_value = 0; i_value < loc_proj_info->nitems; i_value++) sprintf(error_msg + strlen(error_msg), "%s: %s\n", @@ -248,22 +249,22 @@ void check_projection(struct Cell_head *cellhd, GDALDatasetH hDS, int layer, strcat(error_msg, "\n"); } else { - strcat(error_msg, _("Location PROJ_INFO is:\n")); + strcat(error_msg, _("Project PROJ_INFO is:\n")); if (loc_wind.proj == PROJECTION_XY) sprintf(error_msg + strlen(error_msg), - "Location proj = %d (unreferenced/unknown)\n", + "Project proj = %d (unreferenced/unknown)\n", loc_wind.proj); else if (loc_wind.proj == PROJECTION_LL) sprintf(error_msg + strlen(error_msg), - "Location proj = %d (lat/long)\n", + "Project proj = %d (lat/long)\n", loc_wind.proj); else if (loc_wind.proj == PROJECTION_UTM) sprintf(error_msg + strlen(error_msg), - "Location proj = %d (UTM), zone = %d\n", + "Project proj = %d (UTM), zone = %d\n", loc_wind.proj, cellhd->zone); else sprintf(error_msg + strlen(error_msg), - "Location proj = %d (unknown), zone = %d\n", + "Project proj = %d (unknown), zone = %d\n", loc_wind.proj, cellhd->zone); } @@ -337,7 +338,7 @@ void check_projection(struct Cell_head *cellhd, GDALDatasetH hDS, int layer, else { /* error in proj_units */ if (loc_proj_units != NULL) { - strcat(error_msg, "Location PROJ_UNITS is:\n"); + strcat(error_msg, "Project PROJ_UNITS is:\n"); for (i_value = 0; i_value < loc_proj_units->nitems; i_value++) sprintf(error_msg + strlen(error_msg), "%s: %s\n", @@ -355,13 +356,14 @@ void check_projection(struct Cell_head *cellhd, GDALDatasetH hDS, int layer, } } if (!check_only) { - strcat(error_msg, _("\nIn case of no significant differences " - "in the projection definitions," - " use the -o flag to ignore them and use" - " current location definition.\n")); - strcat(error_msg, _("Consider generating a new location from " + strcat(error_msg, + _("\nIn case of no significant differences " + "in the coordinate reference system definitions," + " use the -o flag to ignore them and use" + " current project definition.\n")); + strcat(error_msg, _("Consider generating a new project from " "the input dataset using " - "the 'location' parameter.\n")); + "the 'project' parameter.\n")); } if (check_only) @@ -379,8 +381,8 @@ void check_projection(struct Cell_head *cellhd, GDALDatasetH hDS, int layer, msg_fn = G_message; else msg_fn = G_verbose_message; - msg_fn(_("Projection of input dataset and current location " - "appear to match")); + msg_fn(_("Coordinate reference system of input dataset and current " + "project appear to match")); if (check_only) { GDALClose(hDS); exit(EXIT_SUCCESS); diff --git a/vector/v.in.lidar/main.c b/vector/v.in.lidar/main.c index 76bc0ef540e..8db7d1e3ee6 100644 --- a/vector/v.in.lidar/main.c +++ b/vector/v.in.lidar/main.c @@ -270,10 +270,10 @@ int main(int argc, char *argv[]) limit_opt->guisection = _("Decimation"); outloc_opt = G_define_option(); - outloc_opt->key = "location"; + outloc_opt->key = "project"; outloc_opt->type = TYPE_STRING; outloc_opt->required = NO; - outloc_opt->description = _("Name for new location to create"); + outloc_opt->description = _("Name for new project (location) to create"); outloc_opt->key_desc = "name"; print_flag = G_define_flag(); @@ -319,15 +319,16 @@ int main(int argc, char *argv[]) over_flag = G_define_flag(); over_flag->key = 'o'; over_flag->label = - _("Override projection check (use current location's projection)"); - over_flag->description = _( - "Assume that the dataset has same projection as the current location"); + _("Override projection check (use current project's CRS)"); + over_flag->description = + _("Assume that the dataset has the same coordinate reference system as " + "the current project"); no_import_flag = G_define_flag(); no_import_flag->key = 'i'; - no_import_flag->description = _( - "Create the location specified by the \"location\" parameter and exit." - " Do not import the vector data."); + no_import_flag->description = + _("Create the project specified by the \"project\" parameter and exit." + " Do not import the vector data."); no_import_flag->suppress_required = YES; G_option_exclusive(skip_opt, preserve_opt, NULL); @@ -512,16 +513,16 @@ int main(int argc, char *argv[]) * assume the user has a terminal open */ if (GPJ_wkt_to_grass(&cellhd, &proj_info, &proj_units, projstr, 0) < 0) { - G_fatal_error(_("Unable to convert input map projection to GRASS " - "format; cannot create new location.")); + G_fatal_error(_("Unable to convert input map CRS to GRASS " + "format; cannot create new project.")); } else { if (0 != G_make_location(outloc_opt->answer, &cellhd, proj_info, proj_units)) { - G_fatal_error(_("Unable to create new location <%s>"), + G_fatal_error(_("Unable to create new project <%s>"), outloc_opt->answer); } - G_message(_("Location <%s> created"), outloc_opt->answer); + G_message(_("Project <%s> created"), outloc_opt->answer); } /* If the i flag is set, clean up? and exit here */ @@ -529,7 +530,7 @@ int main(int argc, char *argv[]) exit(EXIT_SUCCESS); /* TODO: */ - G_warning("Import into new location not yet implemented"); + G_warning("Import into new project not yet implemented"); /* at this point the module should be using G_create_alt_env() to change context to the newly created location; once done it should switch back with G_switch_env(). See r.in.gdal */ diff --git a/vector/v.in.lidar/projection.c b/vector/v.in.lidar/projection.c index 44dc7c680d3..aba51081b91 100644 --- a/vector/v.in.lidar/projection.c +++ b/vector/v.in.lidar/projection.c @@ -27,8 +27,8 @@ void projection_mismatch_report(struct Cell_head cellhd, int i_value; char error_msg[8192]; - strcpy(error_msg, _("Projection of dataset does not" - " appear to match current location.\n\n")); + strcpy(error_msg, _("Coordinate reference system of dataset does not" + " appear to match current project.\n\n")); /* TODO: output this info sorted by key: */ if (loc_wind.proj != cellhd.proj || err != -2) { @@ -84,12 +84,12 @@ void projection_mismatch_report(struct Cell_head cellhd, } } sprintf(error_msg + strlen(error_msg), - _("\nIn case of no significant differences in the projection " - "definitions," + _("\nIn case of no significant differences" + " in the coordinate reference system definitions," " use the -o flag to ignore them and use" - " current location definition.\n")); + " current project definition.\n")); strcat(error_msg, - _("Consider generating a new location with 'location' parameter" + _("Consider generating a new project with 'project' parameter" " from input data set.\n")); G_fatal_error("%s", error_msg); } @@ -130,7 +130,8 @@ void projection_check_wkt(struct Cell_head cellhd, struct Cell_head loc_wind, loc_proj_units, proj_info, proj_units, err); } else if (verbose) { - G_message(_("Projection of input dataset and current location " - "appear to match")); + G_message(_( + "Coordinate reference system of input dataset and current project " + "appear to match")); } } diff --git a/vector/v.in.lidar/v.in.lidar.html b/vector/v.in.lidar/v.in.lidar.html index 04c76c0e281..72177b9f5ed 100644 --- a/vector/v.in.lidar/v.in.lidar.html +++ b/vector/v.in.lidar/v.in.lidar.html @@ -91,7 +91,7 @@

Project Creation

If the user wishes to import the data with the full CRS definition, it is possible to have v.in.lidar automatically create a new project based on the CRS and extents of the file being read. This is accomplished -by passing the name to be used for the new project via the location +by passing the name to be used for the new project via the project parameter. Upon completion of the command, a new project will have been created (with only a PERMANENT mapset), and the vector map will have been imported with the indicated output name into the PERMANENT mapset. @@ -116,7 +116,7 @@

EXAMPLE

v.in.lidar -p input="Serpent Mound Model LAS Data.las" # create a project with CRS information of the LAS data - v.in.lidar -i input="Serpent Mound Model LAS Data.las" location=Serpent_Mound + v.in.lidar -i input="Serpent Mound Model LAS Data.las" project=Serpent_Mound # quit and restart GRASS in the newly created project "Serpent_Mound" # real import of LiDAR LAS data, without topology and without attribute table diff --git a/vector/v.in.pdal/main.cpp b/vector/v.in.pdal/main.cpp index 9348463ecc3..0f48e1d5fea 100644 --- a/vector/v.in.pdal/main.cpp +++ b/vector/v.in.pdal/main.cpp @@ -212,19 +212,20 @@ int main(int argc, char *argv[]) Flag *reproject_flag = G_define_flag(); reproject_flag->key = 'w'; reproject_flag->label = - _("Reproject to location's coordinate system if needed"); + _("Reproject to projects's coordinate system if needed"); reproject_flag->description = _("Reprojects input dataset to the coordinate system of" - " the GRASS location (by default only datasets with the" + " the GRASS project (by default only datasets with the" " matching coordinate system can be imported"); reproject_flag->guisection = _("Projection"); Flag *over_flag = G_define_flag(); over_flag->key = 'o'; over_flag->label = - _("Override projection check (use current location's projection)"); - over_flag->description = _( - "Assume that the dataset has same projection as the current location"); + _("Override projection check (use current project's CRS)"); + over_flag->description = + _("Assume that the dataset has the same coordinate reference system as " + "the current project"); over_flag->guisection = _("Projection"); // TODO: from the API it seems that also prj file path and proj string will @@ -347,7 +348,7 @@ int main(int argc, char *argv[]) // we reproject when requested regardless the input projection if (reproject_flag->answer) { - G_message(_("Reprojecting the input to the location projection")); + G_message(_("Reprojecting the input to the project's CRS")); char *proj_wkt = location_projection_as_wkt(false); pdal::Options o4; // TODO: try catch for user input error @@ -370,8 +371,8 @@ int main(int argc, char *argv[]) // getting projection is possible only after prepare if (over_flag->answer) { G_important_message(_("Overriding projection check and assuming" - " that the projection of input matches" - " the location projection")); + " that the CRS of input matches" + " the project's CRS")); } else if (!reproject_flag->answer) { pdal::SpatialReference spatial_reference = diff --git a/vector/v.in.pdal/projection.c b/vector/v.in.pdal/projection.c index 244ee323afb..aa811a0a409 100644 --- a/vector/v.in.pdal/projection.c +++ b/vector/v.in.pdal/projection.c @@ -27,8 +27,8 @@ void projection_mismatch_report(struct Cell_head cellhd, int i_value; char error_msg[8192]; - strcpy(error_msg, _("Projection of dataset does not" - " appear to match current location.\n\n")); + strcpy(error_msg, _("Coordinate reference system of the dataset does not" + " appear to match current project.\n\n")); /* TODO: output this info sorted by key: */ if (loc_wind.proj != cellhd.proj || err != -2) { @@ -84,12 +84,12 @@ void projection_mismatch_report(struct Cell_head cellhd, } } sprintf(error_msg + strlen(error_msg), - _("\nIn case of no significant differences in the projection " - "definitions," + _("\nIn case of no significant differences" + " in the coordinate reference system definitions," " use the -o flag to ignore them and use" - " current location definition.\n")); + " current project definition.\n")); strcat(error_msg, - _("Consider generating a new location with 'location' parameter" + _("Consider generating a new project with 'project' parameter" " from input data set.\n")); G_fatal_error("%s", error_msg); } @@ -131,8 +131,8 @@ void projection_check_wkt(struct Cell_head cellhd, struct Cell_head loc_wind, } else { if (verbose) { - G_message(_("Projection of input dataset and current location " - "appear to match")); + G_message(_("Coordinate reference system of the input dataset and " + "current project appear to match")); } } } From 835afb4352dd4c07654fda044b5ece74fac7b28c Mon Sep 17 00:00:00 2001 From: kpolchow <96669678+kpolchow@users.noreply.github.com> Date: Wed, 24 Apr 2024 09:49:15 -0400 Subject: [PATCH 24/27] contributing: Add security policy (#3544) A basic security policy file covering the current focus areas. It will serve as an input for the public view in the Security tab on GitHub. It does not cover supported version because that's what we (will) cover in a separate document (release policy, release schedule or roadmap). --------- Co-authored-by: Vaclav Petras Co-authored-by: Kira Polchow --- SECURITY.md | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 SECURITY.md diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 00000000000..f722250e8c1 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,38 @@ +# GRASS GIS Security Policy + +## Reporting a Vulnerability +At GRASS GIS, we take security vulnerabilities seriously. We appreciate your efforts in responsibly disclosing any issues you may find. To report a security vulnerability, please follow these steps: +1. **Privately disclose the issue** by submitting a Security Advisory through [GitHub Security](https://github.com/OSGeo/grass/security). Please do not create publicly viewable issues for security vulnerabilities. +2. **Provide detailed information** regarding the vulnerability, including: + - Description of the vulnerability + - Steps to reproduce + - Versions affected + - Any mitigating factors +3. **Our Response**: + - Our security team will acknowledge receiving your report within 48 hours. + - We will work to validate and reproduce the issue. + - Once confirmed, we will work on a fix and release schedule. +4. **Public Disclosure**: + - We aim to release patches for vulnerabilities as soon as possible. + - We will coordinate with you regarding public disclosure, ensuring a reasonable timeline for users to update before the details are made public. + + +## Supported Versions +Please refer to our [Release Schedule](https://trac.osgeo.org/grass/wiki/Release/Schedule) for details on which versions are currently supported. + + +## Security Measures +- Code Review: We conduct code reviews to catch potential vulnerabilities during code submission +- Dependency Management: We track dependencies and update them regularly to mitigate known security issues. +- Secure Development Practices: We use a series of security tools to detect potential vulnerabilities in existing and newly submitted code. + + +## Vulnerability Scope +Our security policy covers vulnerabilities in the GRASS GIS core codebase, official addons, and any official distributions provided by the GRASS GIS team. + +While packages in Linux and other unix-like distributions are out of scope of this document, distribution maintainers traditionally do a great job in patching their distributions for security vulnerabilities. Please, refer to a specific distribution or package source if you are using packages for a specific software distribution. + +## Responsible Disclosure +We adhere to responsible disclosure practices. We appreciate your cooperation in allowing us time to address any reported vulnerabilities before disclosing them publicly. We ask that you refrain from disclosing any details of the vulnerability until we have had adequate time to provide a fix. + +Thank you for helping to keep GRASS GIS secure! From 31e6adece7d7fd1731f3650a6616d125d8839d1e Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 25 Apr 2024 07:41:40 -0400 Subject: [PATCH 25/27] CI(deps): Update actions/download-artifact action to v4.1.7 (#3664) --- .github/workflows/post-pr-reviews.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/post-pr-reviews.yml b/.github/workflows/post-pr-reviews.yml index 729e501fd95..7bfa9b9091f 100644 --- a/.github/workflows/post-pr-reviews.yml +++ b/.github/workflows/post-pr-reviews.yml @@ -19,7 +19,7 @@ jobs: steps: - name: Create a .git directory needed by reviewdog run: git init - - uses: actions/download-artifact@9c19ed7fe5d278cd354c7dfd5d3b88589c7e2395 # v4.1.6 + - uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e # v4.1.7 id: diff continue-on-error: true with: From f5862c7683d31acede7e02f9c2fbeb67a7abaefb Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 25 Apr 2024 11:50:11 +0000 Subject: [PATCH 26/27] CI(deps): Update peter-evans/create-pull-request action to v6.0.5 (#3666) --- .github/workflows/periodic_update.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/periodic_update.yml b/.github/workflows/periodic_update.yml index 4b8cd94580b..b5a5715e8db 100644 --- a/.github/workflows/periodic_update.yml +++ b/.github/workflows/periodic_update.yml @@ -33,7 +33,7 @@ jobs: run: git status --ignored - name: Create Pull Request id: cpr - uses: peter-evans/create-pull-request@9153d834b60caba6d51c9b9510b087acf9f33f83 # v6.0.4 + uses: peter-evans/create-pull-request@6d6857d36972b65feb161a90e484f2984215f83e # v6.0.5 with: commit-message: "config.guess + config.sub: updated from http://git.savannah.gnu.org/cgit/config.git/plain/" branch: periodic/update-configure From 8cbe8fef7c6bc36ad590f724c56508bd32a552f6 Mon Sep 17 00:00:00 2001 From: Anna Petrasova Date: Thu, 25 Apr 2024 16:51:01 -0400 Subject: [PATCH 27/27] contributing: add code of conduct (#3663) --- CODE_OF_CONDUCT.md | 133 +++++++++++++++++++++++++++++++++++++++++++++ README.md | 1 + 2 files changed, 134 insertions(+) create mode 100644 CODE_OF_CONDUCT.md diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 00000000000..0b17de48af4 --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,133 @@ + +# Contributor Covenant Code of Conduct + +## Our Pledge + +We as members, contributors, and leaders pledge to make participation in our +community a harassment-free experience for everyone, regardless of age, body +size, visible or invisible disability, ethnicity, sex characteristics, gender +identity and expression, level of experience, education, socio-economic status, +nationality, personal appearance, race, caste, color, religion, or sexual +identity and orientation. + +We pledge to act and interact in ways that contribute to an open, welcoming, +diverse, inclusive, and healthy community. + +## Our Standards + +Examples of behavior that contributes to a positive environment for our +community include: + +* Demonstrating empathy and kindness toward other people +* Being respectful of differing opinions, viewpoints, and experiences +* Giving and gracefully accepting constructive feedback +* Accepting responsibility and apologizing to those affected by our mistakes, + and learning from the experience +* Focusing on what is best not just for us as individuals, but for the overall + community + +Examples of unacceptable behavior include: + +* The use of sexualized language or imagery, and sexual attention or advances of + any kind +* Trolling, insulting or derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or email address, + without their explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Enforcement Responsibilities + +Community leaders are responsible for clarifying and enforcing our standards of +acceptable behavior and will take appropriate and fair corrective action in +response to any behavior that they deem inappropriate, threatening, offensive, +or harmful. + +Community leaders have the right and responsibility to remove, edit, or reject +comments, commits, code, wiki edits, issues, and other contributions that are +not aligned to this Code of Conduct, and will communicate reasons for moderation +decisions when appropriate. + +## Scope + +This Code of Conduct applies within all community spaces, and also applies when +an individual is officially representing the community in public spaces. +Examples of representing our community include using an official email address, +posting via an official social media account, or acting as an appointed +representative at an online or offline event. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported to the community leaders responsible for enforcement at +[grass-coc@osgeo.org](mailto:grass-coc@osgeo.org). +All complaints will be reviewed and investigated promptly and fairly. + +All community leaders are obligated to respect the privacy and security of the +reporter of any incident. + +## Enforcement Guidelines + +Community leaders will follow these Community Impact Guidelines in determining +the consequences for any action they deem in violation of this Code of Conduct: + +### 1. Correction + +**Community Impact**: Use of inappropriate language or other behavior deemed +unprofessional or unwelcome in the community. + +**Consequence**: A private, written warning from community leaders, providing +clarity around the nature of the violation and an explanation of why the +behavior was inappropriate. A public apology may be requested. + +### 2. Warning + +**Community Impact**: A violation through a single incident or series of +actions. + +**Consequence**: A warning with consequences for continued behavior. No +interaction with the people involved, including unsolicited interaction with +those enforcing the Code of Conduct, for a specified period of time. This +includes avoiding interactions in community spaces as well as external channels +like social media. Violating these terms may lead to a temporary or permanent +ban. + +### 3. Temporary Ban + +**Community Impact**: A serious violation of community standards, including +sustained inappropriate behavior. + +**Consequence**: A temporary ban from any sort of interaction or public +communication with the community for a specified period of time. No public or +private interaction with the people involved, including unsolicited interaction +with those enforcing the Code of Conduct, is allowed during this period. +Violating these terms may lead to a permanent ban. + +### 4. Permanent Ban + +**Community Impact**: Demonstrating a pattern of violation of community +standards, including sustained inappropriate behavior, harassment of an +individual, or aggression toward or disparagement of classes of individuals. + +**Consequence**: A permanent ban from any sort of public interaction within the +community. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], +version 2.1, available at +[https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1]. + +Community Impact Guidelines were inspired by +[Mozilla's code of conduct enforcement ladder][Mozilla CoC]. + +For answers to common questions about this code of conduct, see the FAQ at +[https://www.contributor-covenant.org/faq][FAQ]. Translations are available at +[https://www.contributor-covenant.org/translations][translations]. + +[homepage]: https://www.contributor-covenant.org +[v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html +[Mozilla CoC]: https://github.com/mozilla/diversity +[FAQ]: https://www.contributor-covenant.org/faq +[translations]: https://www.contributor-covenant.org/translations diff --git a/README.md b/README.md index ce6a2ead887..c7bb195cc6b 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,7 @@ [![Coverity](https://scan.coverity.com/projects/1038/badge.svg)](https://scan.coverity.com/projects/grass) [![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.5176030.svg)](https://doi.org/10.5281/zenodo.5176030) [![Join the chat at https://gitter.im/grassgis/community](https://badges.gitter.im/grassgis/community.svg)](https://gitter.im/grassgis/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) +[![Contributor Covenant](https://img.shields.io/badge/Contributor%20Covenant-2.1-4baaaa.svg)](code_of_conduct.md) ## Description