internlm/SWE-Fixer-Train-110K huggingface dataset:
Repository: rasterio/rasterio

Issue:
Use boto3.Session().get_credentials()
In some places (mostly in tests) an [old approach](https://github.com/mapbox/rasterio/blob/3c630f8a30d31ceb61aa52ad3ab96f4fc25f2ecd/rasterio/session.py#L290) to obtain AWS credentials is being used:
```
boto3.Session()._session.get_credentials()
````

Dedicated method to obtain credentials [was added](https://github.com/boto/boto3/commit/982d571ee86f0d8359d338bda66d205fa5713259) more than 5 years ago. Using the official boto3 API seems to be better than relying on properties that are not part of the API.


Discussion:

Resolving patch:
diff --git a/rasterio/session.py b/rasterio/session.py
--- a/rasterio/session.py
+++ b/rasterio/session.py
@@ -287,7 +287,7 @@ def __init__(
         self.unsigned = bool(os.getenv("AWS_NO_SIGN_REQUEST", aws_unsigned))
         self.endpoint_url = endpoint_url
         self._creds = (
-            self._session._session.get_credentials()
+            self._session.get_credentials()
             if not self.unsigned and self._session
             else None
         )


Test patch:
diff --git a/tests/test_env.py b/tests/test_env.py
--- a/tests/test_env.py
+++ b/tests/test_env.py
@@ -26,7 +26,7 @@
 
 # Custom markers.
 credentials = pytest.mark.skipif(
-    not(boto3.Session()._session.get_credentials()),
+    not(boto3.Session().get_credentials()),
     reason="S3 raster access requires credentials")
 
 
diff --git a/tests/test_merge.py b/tests/test_merge.py
--- a/tests/test_merge.py
+++ b/tests/test_merge.py
@@ -72,7 +72,7 @@ def test_unsafe_casting():
 
 
 @pytest.mark.skipif(
-    not (boto3.Session()._session.get_credentials()),
+    not (boto3.Session().get_credentials()),
     reason="S3 raster access requires credentials",
 )
 @pytest.mark.network
diff --git a/tests/test_rio_info.py b/tests/test_rio_info.py
--- a/tests/test_rio_info.py
+++ b/tests/test_rio_info.py
@@ -417,7 +417,7 @@ def test_info_no_credentials(tmpdir, monkeypatch, runner):
         ['info', 'tests/data/RGB.byte.tif'])
     assert result.exit_code == 0
 
-@pytest.mark.skipif(not(boto3.Session()._session.get_credentials()), reason="S3 raster access requires credentials")
+@pytest.mark.skipif(not(boto3.Session().get_credentials()), reason="S3 raster access requires credentials")
 @requires_gdal23(reason="Unsigned S3 requests require GDAL ~= 2.3")
 @pytest.mark.network
 def test_info_aws_unsigned(runner):
diff --git a/tests/test_warpedvrt.py b/tests/test_warpedvrt.py
--- a/tests/test_warpedvrt.py
+++ b/tests/test_warpedvrt.py
@@ -25,7 +25,7 @@
 
 # Custom markers.
 credentials = pytest.mark.skipif(
-    not (boto3.Session()._session.get_credentials()),
+    not (boto3.Session().get_credentials()),
     reason="S3 raster access requires credentials",
 )
Repository: rasterio/rasterio

Issue:
 xy transform with rpcs not sensitive to the input argument z and incorrect
## Expected behavior and actual behavior.

I expect that when applying xy method from https://github.com/rasterio/rasterio/blob/master/rasterio/transform.py by specifying rpcs as TransformMethod the result can be different according to the input argument z.
Moreover, in both cases the output coordinates are far from the true coordinates.

## Steps to reproduce the problem.

```
from rasterio.enums import TransformMethod
import rasterio

with rasterio.open('tests/data/RGB.byte.rpc.vrt', 'r') as test_raster:
    x,y = test_raster.xy(row=0, col=0, z=0, transform_method=TransformMethod.rpcs)
    print(x,y)
    x,y = test_raster.xy(row=0, col=0, z=2000, transform_method=TransformMethod.rpcs)
    print(x,y)
```
Output:
-123.47959047080701 49.52794990575094
-123.47959047080701 49.52794990575094

Expected coordinates (by QGIS)
-78.484675 25.510018

## Operating system

Ubuntu 21.04

## Rasterio version and provenance

rasterio      1.3a3


Discussion:

Resolving patch:
diff --git a/rasterio/transform.py b/rasterio/transform.py
--- a/rasterio/transform.py
+++ b/rasterio/transform.py
@@ -71,7 +71,7 @@ def xy(self, row, col, z=None, offset="center", transform_method=TransformMethod
             transform = transform[0]
         if not transform:
             raise AttributeError("Dataset has no {}".format(transform_method))
-        return xy(transform, row, col, z=z, offset=offset, **rpc_options)
+        return xy(transform, row, col, zs=z, offset=offset, **rpc_options)
 
     def index(self, x, y, z=None, op=math.floor, precision=None, transform_method=TransformMethod.affine, **rpc_options):
         """
@@ -111,7 +111,7 @@ def index(self, x, y, z=None, op=math.floor, precision=None, transform_method=Tr
             transform = transform[0]
         if not transform:
             raise AttributeError("Dataset has no {}".format(transform_method))
-        return rowcol(transform, x, y, z=z, op=op, precision=precision, **rpc_options)
+        return rowcol(transform, x, y, zs=z, op=op, precision=precision, **rpc_options)
 
 def get_transformer(transform, **rpc_options):
     """Return the appropriate transformer class"""


Test patch:
diff --git a/tests/test_transform.py b/tests/test_transform.py
--- a/tests/test_transform.py
+++ b/tests/test_transform.py
@@ -401,3 +401,11 @@ def test_dataset_mixins(dataset, transform_method, expected):
     with rasterio.open(dataset) as src:
         assert src.xy(0, 0, transform_method=transform_method) == pytest.approx(expected)
         assert src.index(*expected, transform_method=transform_method) == (0, 0)
+
+def test_2421_rpc_height_ignored():
+    transform_method = rasterio.enums.TransformMethod.rpcs
+    with rasterio.open("tests/data/RGB.byte.rpc.vrt") as src:
+        x1, y1 = src.xy(0, 0, z=0, transform_method=transform_method)
+        x2, y2 = src.xy(0, 0, z=2000, transform_method=transform_method)
+        assert abs(x2 - x1) > 0
+        assert abs(y2 - y1) > 0
\ No newline at end of file
Repository: rasterio/rasterio

Issue:
DOC: Intersphinx with GDAL
[intersphinx](https://www.sphinx-doc.org/en/master/usage/extensions/intersphinx.html) could be a potential help to provide a link to the GDAL docs within the rasterio docs.

pyproj usage example with PROJ:
- https://github.com/pyproj4/pyproj/blob/57ecfc881808318574d580c56c5415652dfea3ec/docs/conf.py#L44-L46
- https://github.com/pyproj4/pyproj/blob/57ecfc881808318574d580c56c5415652dfea3ec/pyproj/crs/crs.py#L1065

For example, [rasterio.warp.reproject](https://rasterio.readthedocs.io/en/latest/api/rasterio.warp.html#rasterio.warp.reproject) says:

```
kwargs (dict, optional) – Additional arguments passed to transformation function.
```

For users familiar with the GDAL C code, finding the options in the GDAL docs is not terrible. But, for the average user, they may not know where to find out what those arguments are and links would probably be very helpful:

- https://gdal.org/api/gdalwarp_cpp.html#_CPPv415GDALWarpOptions
- https://gdal.org/api/gdal_alg.html#_CPPv432GDALCreateGenImgProjTransformer212GDALDatasetH12GDALDatasetHPPc



Discussion:

Resolving patch:
diff --git a/docs/conf.py b/docs/conf.py
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -28,6 +28,7 @@
 extensions = [
     'sphinx.ext.autodoc',
     'sphinx.ext.doctest',
+    'sphinx.ext.intersphinx',
     'sphinx.ext.napoleon',
     'sphinx.ext.todo',
 ]
@@ -363,4 +364,7 @@
 
 
 # Example configuration for intersphinx: refer to the Python standard library.
-intersphinx_mapping = {'https://docs.python.org/': None}
+intersphinx_mapping = {
+    "python": ("https://docs.python.org/", None),
+    "gdal": ("https://gdal.org/", None),
+}
diff --git a/rasterio/warp.py b/rasterio/warp.py
--- a/rasterio/warp.py
+++ b/rasterio/warp.py
@@ -259,7 +259,10 @@ def reproject(source, destination=None, src_transform=None, gcps=None, rpcs=None
         raster to a destination of the same size is approximately
         56 MB. The default (0) means 64 MB with GDAL 2.2.
     kwargs:  dict, optional
-        Additional arguments passed to transformation function.
+        Additional arguments passed to both the image to image
+        transformer :cpp:func:`GDALCreateGenImgProjTransformer2` (for example,
+        MAX_GCP_ORDER=2) and the :cpp:struct:`GDALWarpOptions` (for example,
+        INIT_DEST=NO_DATA).
 
     Returns
     ---------


Test patch:
Repository: rasterio/rasterio

Issue:
WindowMethodsMixin::window() uses deprecated arguments
`WindowMethodsMixin::window()` calls `rasterio.windows.from_bounds()` with [deprecated arguments](https://rasterio.readthedocs.io/en/latest/api/rasterio.windows.html#rasterio.windows.from_bounds) `width` and `height` (see [here](https://github.com/rasterio/rasterio/blob/master/rasterio/windows.py#L84-L85)). This issues a `RasterioDeprecationWarning` even if the user does not use these deprecated parameters directly.


Discussion:
A PR with a fix is welcome.

Resolving patch:
diff --git a/rasterio/windows.py b/rasterio/windows.py
--- a/rasterio/windows.py
+++ b/rasterio/windows.py
@@ -60,7 +60,7 @@ def window(self, left, bottom, right, top, precision=None):
         top: float
             Top (north) bounding coordinate
         precision: int, optional
-            This parameters is unused, deprecated in rasterio 1.3.0, and
+            This parameter is unused, deprecated in rasterio 1.3.0, and
             will be removed in version 2.0.0.
 
         Returns
@@ -74,15 +74,12 @@ def window(self, left, bottom, right, top, precision=None):
                 RasterioDeprecationWarning,
             )
 
-        transform = guard_transform(self.transform)
         return from_bounds(
             left,
             bottom,
             right,
             top,
-            transform=transform,
-            height=self.height,
-            width=self.width,
+            transform=guard_transform(self.transform),
         )
 
     def window_transform(self, window):


Test patch:
Repository: rasterio/rasterio

Issue:
Deal with PROJ_DATA environment variable
PROJ 9.1 recognizes the PROJ_DATA environment variable, as a replacement
for PROJ_LIB (both are still recognized by PROJ >= 9.1. PROJ_LIB will be
retired in PROJ 10, whose release is unplanned for now)

Cf https://github.com/OSGeo/PROJ/pull/3253


Discussion:
Thanks @rouault !

Resolving patch:
diff --git a/rasterio/env.py b/rasterio/env.py
--- a/rasterio/env.py
+++ b/rasterio/env.py
@@ -646,7 +646,12 @@ def wrapper(*args, **kwds):
             set_gdal_config("GDAL_DATA", path)
             log.debug("GDAL data found in other locations: path=%r.", path)
 
-if "PROJ_LIB" in os.environ:
+if "PROJ_DATA" in os.environ:
+    # PROJ 9.1+
+    path = os.environ["PROJ_DATA"]
+    set_proj_data_search_path(path)
+elif "PROJ_LIB" in os.environ:
+    # PROJ < 9.1
     path = os.environ["PROJ_LIB"]
     set_proj_data_search_path(path)
 
diff --git a/rasterio/rio/env.py b/rasterio/rio/env.py
--- a/rasterio/rio/env.py
+++ b/rasterio/rio/env.py
@@ -29,4 +29,4 @@ def env(ctx, key):
         elif key == 'gdal_data':
             click.echo(os.environ.get('GDAL_DATA') or GDALDataFinder().search())
         elif key == 'proj_data':
-            click.echo(os.environ.get('PROJ_LIB') or PROJDataFinder().search())
+            click.echo(os.environ.get('PROJ_DATA', os.environ.get('PROJ_LIB')) or PROJDataFinder().search())
diff --git a/setup.py b/setup.py
--- a/setup.py
+++ b/setup.py
@@ -154,8 +154,8 @@ def copy_data_tree(datadir, destdir):
             log.info("Copying gdal_data from %s" % gdal_data)
             copy_data_tree(gdal_data, destdir)
 
-    # Conditionally copy PROJ.4 data.
-    projdatadir = os.environ.get('PROJ_LIB', '/usr/local/share/proj')
+    # Conditionally copy PROJ DATA.
+    projdatadir = os.environ.get('PROJ_DATA', os.environ.get('PROJ_LIB', '/usr/local/share/proj'))
     if os.path.exists(projdatadir):
         log.info("Copying proj_data from %s" % projdatadir)
         copy_data_tree(projdatadir, 'rasterio/proj_data')


Test patch:
diff --git a/tests/test_crs.py b/tests/test_crs.py
--- a/tests/test_crs.py
+++ b/tests/test_crs.py
@@ -356,8 +356,9 @@ def test_dataset_compound_crs():
 
 @pytest.mark.wheel
 def test_environ_patch(gdalenv, monkeypatch):
-    """PROJ_LIB is patched when rasterio._crs is imported"""
+    """PROJ_LIB (PROJ < 9.1) | PROJ_DATA (PROJ 9.1+) is patched when rasterio._crs is imported"""
     monkeypatch.delenv('GDAL_DATA', raising=False)
+    monkeypatch.delenv('PROJ_DATA', raising=False)
     monkeypatch.delenv('PROJ_LIB', raising=False)
     with env_ctx_if_needed():
         assert CRS.from_epsg(4326) != CRS(units='m', proj='aeqd', ellps='WGS84', datum='WGS84', lat_0=-17.0, lon_0=-44.0)
Repository: rasterio/rasterio

Issue:
DOC: CLI documentation down
Hello, 

Just an issue to report that your documentation regarding the api seems not to work.
ex : 
https://rasterio.readthedocs.io/en/latest/api/rasterio.rio.bounds.html

You might have a problem with your sphinx deployment pipeline



Discussion:
As a workaround, you can access previous documentations by selecting the green `v: latest` button on the lower-left corner, and selecting the "Stable" version.
Setting version to stable doesn't work for me, it appears the same as latest does 😱 
One option could be to use GitHub pages instead of RTD similar to pyproj: https://github.com/pyproj4/pyproj/blob/main/.github/workflows/build_docs.yaml
@rasterio/maintainers, thoughts about switching to use GitHub pages? If we do, we can control the build environment instead of relying on the RTD build environment.
```
WARNING: autodoc: failed to import module 'rasterio'; the following exception was raised:
libtiledb.so.2.2: cannot open shared object file: No such file or directory
```
Originally posted by @loicdtx in https://github.com/rasterio/rasterio/issues/2480#issue-1271897697

We use conda-forge packages on RTD and every once in a while, conda-forge's GDAL dependencies are busted. I'll login and rebuild.
I fixed this in 558bddf5. I'm not sure how I lost track of the importance of putting conda-forge above defaults in the channels array.
I am reopening as the issue presented here is still relevant. Although the RTD build issue has been addressed, the CLI documentation referenced at the top of this issue is still not showing up.

Thoughts about using https://github.com/click-contrib/sphinx-click for the CLI documentation?

Resolving patch:
diff --git a/docs/conf.py b/docs/conf.py
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -31,6 +31,7 @@
     'sphinx.ext.intersphinx',
     'sphinx.ext.napoleon',
     'sphinx.ext.todo',
+    'sphinx_click',
 ]
 
 # Add any paths that contain templates here, relative to this directory.
diff --git a/rasterio/rio/blocks.py b/rasterio/rio/blocks.py
--- a/rasterio/rio/blocks.py
+++ b/rasterio/rio/blocks.py
@@ -117,13 +117,13 @@ def blocks(
     option:
     \b
 
-        $ rio shapes --bidx 3 tests/data/RGB.byte.tif
+        $ rio blocks --bidx 3 tests/data/RGB.byte.tif
 
     By default a GeoJSON 'FeatureCollection' is written, but the --sequence'
     option produces a GeoJSON feature stream instead.
     \b
 
-        $ rio shapes tests/data/RGB.byte.tif --sequence
+        $ rio blocks tests/data/RGB.byte.tif --sequence
 
     Output features are reprojected to 'WGS84' unless the '--projected' flag is
     provided, which causes the output to be kept in the input datasource's
diff --git a/setup.py b/setup.py
--- a/setup.py
+++ b/setup.py
@@ -274,7 +274,13 @@ def copy_data_tree(datadir, destdir):
 ]
 
 extra_reqs = {
-    "docs": ["ghp-import", "numpydoc", "sphinx", "sphinx-rtd-theme"],
+    "docs": [
+        "ghp-import",
+        "numpydoc",
+        "sphinx",
+        "sphinx-click",
+        "sphinx-rtd-theme",
+    ],
     "ipython": ["ipython>=2.0"],
     "plot": ["matplotlib"],
     "s3": ["boto3>=1.2.4"],


Test patch:
Repository: rasterio/rasterio

Issue:
ENH: Add support for RFC 87: Signed int8 data type for raster
        Cf https://github.com/OSGeo/gdal/pull/6634 "RFC 87: Signed int8 data type for raster" that will likely be implemented in GDAL 3.7

_Originally posted by @rouault in https://github.com/rasterio/rasterio/issues/1595#issuecomment-1307086052_
      


Discussion:

Resolving patch:
diff --git a/rasterio/dtypes.py b/rasterio/dtypes.py
--- a/rasterio/dtypes.py
+++ b/rasterio/dtypes.py
@@ -10,6 +10,7 @@
 from rasterio.env import GDALVersion
 
 _GDAL_AT_LEAST_35 = GDALVersion.runtime().at_least("3.5")
+_GDAL_AT_LEAST_37 = GDALVersion.runtime().at_least("3.7")
 
 bool_ = 'bool'
 ubyte = uint8 = 'uint8'
@@ -47,10 +48,15 @@
     dtype_fwd[12] = int64 # GDT_Int64
     dtype_fwd[13] = uint64 # GDT_UInt64
 
+if _GDAL_AT_LEAST_37:
+    dtype_fwd[14] = sbyte # GDT_Int8
+
 dtype_rev = dict((v, k) for k, v in dtype_fwd.items())
 
 dtype_rev["uint8"] = 1
-dtype_rev["int8"] = 1
+if not _GDAL_AT_LEAST_37:
+    dtype_rev["int8"] = 1
+
 dtype_rev["complex"] = 11
 dtype_rev["complex_int16"] = 8
 
@@ -82,6 +88,9 @@ def _get_gdal_dtype(type_name):
     typename_fwd[12] = 'Int64'
     typename_fwd[13] = 'UInt64'
 
+if _GDAL_AT_LEAST_37:
+    typename_fwd[14] = 'Int8'
+
 typename_rev = dict((v, k) for k, v in typename_fwd.items())
 
 dtype_ranges = {


Test patch:
diff --git a/tests/test_int8.py b/tests/test_int8.py
--- a/tests/test_int8.py
+++ b/tests/test_int8.py
@@ -3,9 +3,12 @@
 import pytest
 
 import rasterio
+from rasterio.env import GDALVersion
 
+gdal_version = GDALVersion.runtime()
 
-@pytest.mark.xfail(reason="Likely upstream bug")
+
+@pytest.mark.xfail(gdal_version < GDALVersion(3, 7), reason="GDAL < 3.7 doesn't handle signed int8 correctly")
 @pytest.mark.parametrize("nodata", [-1, -128])
 def test_write_int8_mem(nodata):
     profile = {
diff --git a/tests/test_write.py b/tests/test_write.py
--- a/tests/test_write.py
+++ b/tests/test_write.py
@@ -12,10 +12,9 @@
 import rasterio
 from rasterio.drivers import blacklist
 from rasterio.enums import MaskFlags, Resampling
-from rasterio.env import Env
+from rasterio.env import Env, GDALVersion
 from rasterio.errors import RasterioIOError
 
-
 def test_validate_dtype_None(tmpdir):
     """Raise TypeError if there is no dtype"""
     name = str(tmpdir.join("lol.tif"))
@@ -118,7 +117,10 @@ def test_write_sbyte(tmpdir):
 
     info = subprocess.check_output(["gdalinfo", "-stats", name]).decode('utf-8')
     assert "Minimum=-33.000, Maximum=-33.000, Mean=-33.000, StdDev=0.000" in info
-    assert 'SIGNEDBYTE' in info
+    if GDALVersion.runtime() < GDALVersion(3, 7):
+        assert 'SIGNEDBYTE' in info
+    else:
+        assert 'Int8' in info
 
 
 @pytest.mark.gdalbin
Repository: rasterio/rasterio

Issue:
DOC: Documentation inconsistency in rasterio.features.rasterize
The `out` parameter of `rasterio.features.rasterize`'s documentation mentions a `source` but there is no parameter called source it is not clear what size it needs to be in this case, or if it matters.

https://github.com/rasterio/rasterio/blob/main/rasterio/features.py#L209 



Discussion:
Thanks for bringing this to our attention. You are correct. I think that it should say something like this:
```
out:
    Array in which to store results. If not provided, out_shape and dtype are required.
```

Resolving patch:
diff --git a/rasterio/features.py b/rasterio/features.py
--- a/rasterio/features.py
+++ b/rasterio/features.py
@@ -206,8 +206,8 @@ def rasterize(
         Used as fill value for all areas not covered by input
         geometries.
     out : numpy.ndarray, optional
-        Array of same shape and data type as `source` in which to store
-        results.
+        Array in which to store results. If not provided, out_shape 
+        and dtype are required.
     transform : Affine transformation object, optional
         Transformation from pixel coordinates of `source` to the
         coordinate system of the input `shapes`. See the `transform`


Test patch:
Repository: rasterio/rasterio

Issue:
ENH: Add int8 to rasterize (GDAL 3.7+)
https://github.com/rasterio/rasterio/blob/7e86f1b745331c4ca57dbf89a704e9bceead11b7/rasterio/features.py#L255

Related: https://github.com/rasterio/rasterio/pull/2656


Discussion:

Resolving patch:
diff --git a/rasterio/features.py b/rasterio/features.py
--- a/rasterio/features.py
+++ b/rasterio/features.py
@@ -256,7 +256,9 @@ def rasterize(
         'int16', 'int32', 'uint8', 'uint16', 'uint32', 'float32', 'float64'
     )
     if GDALVersion.runtime().at_least("3.5"):
-        valid_dtypes = valid_dtypes + ("int64", "uint64")
+        valid_dtypes += ("int64", "uint64")
+    if GDALVersion.runtime().at_least("3.7"):
+        valid_dtypes += ("int8",)
 
     def format_invalid_dtype(param):
         return '{0} dtype must be one of: {1}'.format(


Test patch:
diff --git a/tests/test_features.py b/tests/test_features.py
--- a/tests/test_features.py
+++ b/tests/test_features.py
@@ -750,6 +750,14 @@ def test_rasterize_invalid_value(basic_geometry):
                 gdal_version.at_least("3.5"), reason="GDAL regression? Works with 3.4.3"
             ),
         ),
+        pytest.param(
+            "int8",
+            -128,
+            marks=pytest.mark.skipif(
+                not gdal_version.at_least("3.7"),
+                reason="int8 support added in GDAL 3.7",
+            ),
+        ),
         ("uint8", 255),
         ("uint16", 65535),
         ("float32", 1.434532),
@@ -781,11 +789,12 @@ def test_rasterize_supported_dtype(dtype, default_value, basic_geometry):
 def test_rasterize_unsupported_dtype(basic_geometry):
     """Unsupported types should all raise exceptions."""
     unsupported_types = (
-        ('int8', -127),
-        ('float16', -9343.232)
+        ('float16', -9343.232),
     )
     if not gdal_version.at_least("3.5"):
         unsupported_types += (('int64', 20439845334323),)
+    if not gdal_version.at_least("3.7"):
+        unsupported_types += (('int8', -127),)
 
     for dtype, default_value in unsupported_types:
         with pytest.raises(ValueError):
Repository: python-discord/site

Issue:
Django - Better model validation
**Originally posted by Johannes Christ:**

We still have some places where adding more model validation may be a good idea, such as snake names not containing any numbers or documentation link packages being valid python names.


Discussion:
**Comment from Johannes Christ:**

changed title from **Django{-:-} Better model validation** to **Django{+ -+} Better model validation**
**Comment from Johannes Christ:**

This is now labeled as *good first issue* - it's a good way to learn about Django models and validators. The following documentation links may be of interest:

- https://docs.djangoproject.com/en/2.1/topics/db/models/
- https://docs.djangoproject.com/en/2.1/ref/validators/

If you have any questions, please ask. If you're interested in taking upon this issue, please leave a comment.

Resolving patch:
diff --git a/api/migrations/0021_add_special_snake_validator.py b/api/migrations/0021_add_special_snake_validator.py
new file mode 100644
--- /dev/null
+++ b/api/migrations/0021_add_special_snake_validator.py
@@ -0,0 +1,19 @@
+# Generated by Django 2.1.2 on 2018-11-25 14:59
+
+import django.core.validators
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('api', '0020_add_snake_field_validators'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='specialsnake',
+            name='name',
+            field=models.CharField(help_text='A special snake name.', max_length=140, primary_key=True, serialize=False, validators=[django.core.validators.RegexValidator(regex='^([^0-9])+$')]),
+        ),
+    ]
diff --git a/api/models.py b/api/models.py
--- a/api/models.py
+++ b/api/models.py
@@ -111,7 +111,8 @@ class SpecialSnake(ModelReprMixin, models.Model):
     name = models.CharField(
         max_length=140,
         primary_key=True,
-        help_text='A special snake name.'
+        help_text='A special snake name.',
+        validators=[RegexValidator(regex=r'^([^0-9])+$')]
     )
     info = models.TextField(
         help_text='Info about a special snake.'


Test patch: