Source code for grass.grassdb.create

"""
Create objects in a GRASS project

(C) 2020-2025 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
for details.

.. sectionauthor:: Vaclav Petras <wenzeslaus gmail com>
"""

from __future__ import annotations

import json
import tarfile
import codecs
import os
import shutil
import getpass
from pathlib import Path

from grass.grassdb.manage import resolve_mapset_path, MapsetPath


[docs] def create_xy_project(path: Path | str) -> None: """Create a project with with general cartesian coordinate system (XY) :raises: OSError on error related to the file system """ _create_project_dir(path) # create DEFAULT_WIND and WIND files _add_computation_region_to_project_dir(path, crs_type_code=0)
def _create_project_dir(path: Path | str) -> Path: """Create an empty project directory including directory for the default mapset :returns: Path to the default mapset """ project_dir = Path(path) permanent_dir = project_dir / "PERMANENT" project_dir.mkdir() permanent_dir.mkdir() return permanent_dir def _set_project_description(path: Path | str, text: str): """Set description (aka title aka MYNAME) for a project""" with codecs.open( os.path.join(path, "PERMANENT", "MYNAME"), encoding="utf-8", mode="w", ) as fd: if text: fd.write(text + os.linesep) else: fd.write(os.linesep) def _add_computation_region_to_project_dir( path: Path | str, *, crs_type_code: int | None = None, zone: int | None = None ): """Add computational region to project directory Creates both the default and the current compuational regions. If the file already exists, it is overwritten. """ permanent_dir = Path(path) / "PERMANENT" default_wind_path = permanent_dir / "DEFAULT_WIND" wind_path = permanent_dir / "WIND" size: float = 1 regioninfo = [ f"proj: {crs_type_code if crs_type_code is not None else 0}", f"zone: {zone if zone is not None else 0}", f"north: {size}", "south: 0", f"east: {size}", "west: 0", f"cols: {size}", f"rows: {size}", "e-w resol: 1", "n-s resol: 1", f"top: {size}", "bottom: 0", f"cols3: {size}", f"rows3: {size}", f"depths: {size}", "e-w resol3: 1", "n-s resol3: 1", "t-b resol: 1", ] # create the files default_wind_path.write_text("\n".join(regioninfo)) shutil.copy(default_wind_path, wind_path) def _directory_to_mapset(path: MapsetPath): """Turn an existing directory into a mapset""" # copy DEFAULT_WIND file and its permissions from PERMANENT # to WIND in the new mapset region_path1 = path.path.parent / "PERMANENT" / "DEFAULT_WIND" region_path2 = path.path / "WIND" shutil.copy(region_path1, region_path2)
[docs] def create_mapset(database, location, mapset): """Creates a mapset in a specified location""" path = resolve_mapset_path( database, location, mapset, ) # create an empty directory os.mkdir(path) _directory_to_mapset(path)
# set permissions to u+rw,go+r (disabled; why?) # os.chmod(os.path.join(database,location,mapset,'WIND'), 0644)
[docs] def get_default_mapset_name(): """Returns default name for mapset.""" try: result = getpass.getuser() # Raise error if not ascii (not valid mapset name). result.encode("ascii") except UnicodeEncodeError: # Fall back to fixed name. result = "user" return result
[docs] def create_project_from_pack( path: Path | str, filename: str, description: str | None = None ): """Create project from a GRASS native raster file (aka pack file)""" _create_project_dir(path) set_project_crs_from_pack(path, filename) if description: _set_project_description(path, description)
[docs] def set_project_crs_from_pack(path: Path | str, filename: Path | str): """Set project CRS from a GRASS native raster file. Overwrites the values of the current and the default computational region (if any). """ with tarfile.open(os.fspath(filename)) as tar: data_names = [ tarinfo.name for tarinfo in tar.getmembers() if "/" not in tarinfo.name ] try: tar_info = tar.getmember(data_names[0] + "/computational_region_crs.json") except KeyError as error: msg = "Missing complete CRS info: Use pack from version 8.5 (2025) or above" raise ValueError(msg) from error data = json.loads(tar.extractfile(tar_info).read().decode("utf-8")) _add_computation_region_to_project_dir( path, crs_type_code=data["type_code"], zone=data["zone"], ) crs_files = [ "PROJ_UNITS", "PROJ_INFO", "PROJ_EPSG", "PROJ_SRID", "PROJ_WKT", ] for name in crs_files: try: tar_info = tar.getmember(data_names[0] + "/" + name) except KeyError: continue (Path(path) / "PERMANENT" / name).write_bytes( tar.extractfile(tar_info).read() )