1
0
mirror of https://github.com/django/django.git synced 2025-03-31 11:37:06 +00:00

Merge branch 'django:main' into skushagra-patch-1-issue-35119

This commit is contained in:
Kushagra S 2024-01-25 17:39:25 +05:30 committed by GitHub
commit 70a9abafc9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
12 changed files with 216 additions and 19 deletions

View File

@ -893,11 +893,6 @@ a.deletelink:focus, a.deletelink:hover {
}
}
#footer {
clear: both;
padding: 10px;
}
/* COLUMN TYPES */
.colMS {

View File

@ -451,14 +451,10 @@ input[type="submit"], button {
@media (max-width: 767px) {
/* Layout */
#header, #content, #footer {
#header, #content {
padding: 15px;
}
#footer:empty {
padding: 0;
}
div.breadcrumbs {
padding: 10px 15px;
}

View File

@ -108,9 +108,9 @@
<br class="clear">
</div>
<!-- END Content -->
{% block footer %}<div id="footer"></div>{% endblock %}
</main>
</div>
<footer id="footer">{% block footer %}{% endblock %}</footer>
</div>
<!-- END Container -->

View File

@ -287,6 +287,22 @@ class OGRGeometry(GDALBase):
else:
raise ValueError(f"Input to 'set_3d' must be a boolean, got '{value!r}'.")
@property
def is_measured(self):
"""Return True if the geometry has M coordinates."""
return capi.is_measured(self.ptr)
def set_measured(self, value):
"""Set if this geometry has M coordinates."""
if value is True:
capi.set_measured(self.ptr, 1)
elif value is False:
capi.set_measured(self.ptr, 0)
else:
raise ValueError(
f"Input to 'set_measured' must be a boolean, got '{value!r}'."
)
# #### SpatialReference-related Properties ####
# The SRS property
@ -386,14 +402,22 @@ class OGRGeometry(GDALBase):
sz = self.wkb_size
# Creating the unsigned character buffer, and passing it in by reference.
buf = (c_ubyte * sz)()
capi.to_wkb(self.ptr, byteorder, byref(buf))
# For backward compatibility, export old-style 99-402 extended
# dimension types when geometry does not have an M dimension.
# https://gdal.org/api/vector_c_api.html#_CPPv417OGR_G_ExportToWkb12OGRGeometryH15OGRwkbByteOrderPh
to_wkb = capi.to_iso_wkb if self.is_measured else capi.to_wkb
to_wkb(self.ptr, byteorder, byref(buf))
# Returning a buffer of the string at the pointer.
return memoryview(string_at(buf, sz))
@property
def wkt(self):
"Return the WKT representation of the Geometry."
return capi.to_wkt(self.ptr, byref(c_char_p()))
# For backward compatibility, export old-style 99-402 extended
# dimension types when geometry does not have an M dimension.
# https://gdal.org/api/vector_c_api.html#_CPPv417OGR_G_ExportToWkt12OGRGeometryHPPc
to_wkt = capi.to_iso_wkt if self.is_measured else capi.to_wkt
return to_wkt(self.ptr, byref(c_char_p()))
@property
def ewkt(self):
@ -568,11 +592,21 @@ class Point(OGRGeometry):
if self.is_3d:
return capi.getz(self.ptr, 0)
@property
def m(self):
"""Return the M coordinate for this Point."""
if self.is_measured:
return capi.getm(self.ptr, 0)
@property
def tuple(self):
"Return the tuple of this point."
if self.is_3d and self.is_measured:
return self.x, self.y, self.z, self.m
if self.is_3d:
return (self.x, self.y, self.z)
return self.x, self.y, self.z
if self.is_measured:
return self.x, self.y, self.m
return self.x, self.y
coords = tuple
@ -753,7 +787,9 @@ GEO_CLASSES = {
6: MultiPolygon,
7: GeometryCollection,
101: LinearRing,
1 + OGRGeomType.wkb25bit: Point,
2001: Point, # POINT M
3001: Point, # POINT ZM
1 + OGRGeomType.wkb25bit: Point, # POINT Z
2 + OGRGeomType.wkb25bit: LineString,
3 + OGRGeomType.wkb25bit: Polygon,
4 + OGRGeomType.wkb25bit: MultiPoint,

View File

@ -51,6 +51,7 @@ to_kml = string_output(
getx = pnt_func(lgdal.OGR_G_GetX)
gety = pnt_func(lgdal.OGR_G_GetY)
getz = pnt_func(lgdal.OGR_G_GetZ)
getm = pnt_func(lgdal.OGR_G_GetM)
# Geometry creation routines.
if GDAL_VERSION >= (3, 3):
@ -82,6 +83,8 @@ geom_sym_diff = geom_output(lgdal.OGR_G_SymmetricDifference, [c_void_p, c_void_p
geom_union = geom_output(lgdal.OGR_G_Union, [c_void_p, c_void_p])
is_3d = bool_output(lgdal.OGR_G_Is3D, [c_void_p])
set_3d = void_output(lgdal.OGR_G_Set3D, [c_void_p, c_int], errcheck=False)
is_measured = bool_output(lgdal.OGR_G_IsMeasured, [c_void_p])
set_measured = void_output(lgdal.OGR_G_SetMeasured, [c_void_p, c_int], errcheck=False)
# Geometry modification routines.
add_geom = void_output(lgdal.OGR_G_AddGeometry, [c_void_p, c_void_p])
@ -94,9 +97,13 @@ destroy_geom = void_output(lgdal.OGR_G_DestroyGeometry, [c_void_p], errcheck=Fal
to_wkb = void_output(
lgdal.OGR_G_ExportToWkb, None, errcheck=True
) # special handling for WKB.
to_iso_wkb = void_output(lgdal.OGR_G_ExportToIsoWkb, None, errcheck=True)
to_wkt = string_output(
lgdal.OGR_G_ExportToWkt, [c_void_p, POINTER(c_char_p)], decoding="ascii"
)
to_iso_wkt = string_output(
lgdal.OGR_G_ExportToIsoWkt, [c_void_p, POINTER(c_char_p)], decoding="ascii"
)
to_gml = string_output(
lgdal.OGR_G_ExportToGML, [c_void_p], str_result=True, decoding="ascii"
)
@ -115,7 +122,7 @@ get_geom_srs = srs_output(lgdal.OGR_G_GetSpatialReference, [c_void_p])
get_area = double_output(lgdal.OGR_G_GetArea, [c_void_p])
get_centroid = void_output(lgdal.OGR_G_Centroid, [c_void_p, c_void_p])
get_dims = int_output(lgdal.OGR_G_GetDimension, [c_void_p])
get_coord_dim = int_output(lgdal.OGR_G_GetCoordinateDimension, [c_void_p])
get_coord_dim = int_output(lgdal.OGR_G_CoordinateDimension, [c_void_p])
set_coord_dim = void_output(
lgdal.OGR_G_SetCoordinateDimension, [c_void_p, c_int], errcheck=False
)

View File

@ -488,6 +488,10 @@ class LayerMapping:
if necessary (for example if the model field is MultiPolygonField while
the mapped shapefile only contains Polygons).
"""
# Measured geometries are not yet supported by GeoDjango models.
if geom.is_measured:
geom.set_measured(False)
# Downgrade a 3D geom to a 2D one, if necessary.
if self.coord_dim == 2 and geom.is_3d:
geom.set_3d(False)

View File

@ -581,6 +581,27 @@ coordinate transformation:
>>> p.wkt
"POINT (1 2)"
.. attribute:: is_measured
.. versionadded:: 5.1
A boolean indicating if this geometry has M coordinates.
.. method:: set_measured(value)
.. versionadded:: 5.1
A method to add or remove the M coordinate dimension.
.. code-block:: pycon
>>> p = OGRGeometry("POINT (1 2)")
>>> p.is_measured
False
>>> p.set_measured(True)
>>> p.wkt
"POINT M (1 2 0)"
.. attribute:: geom_count
Returns the number of elements in this geometry:
@ -864,6 +885,18 @@ coordinate transformation:
>>> OGRGeometry("POINT (1 2 3)").z
3.0
.. attribute:: m
.. versionadded:: 5.1
Returns the M coordinate of this point, or ``None`` if the Point does not
have an M coordinate:
.. code-block:: pycon
>>> OGRGeometry("POINT ZM (1 2 3 4)").m
4.0
.. class:: LineString
.. attribute:: x

View File

@ -199,6 +199,39 @@ This logging does not include framework-level initialization (e.g.
``SET TIMEZONE``). Turn on query logging in your database if you wish to view
all database queries.
.. _django-utils-autoreloader-logger:
``django.utils.autoreload``
~~~~~~~~~~~~~~~~~~~~~~~~~~~
Log messages related to automatic code reloading during the execution of the
Django development server. This logger generates an ``INFO`` message upon
detecting a modification in a source code file and may produce ``WARNING``
messages during filesystem inspection and event subscription processes.
.. _django-contrib-gis-logger:
``django.contrib.gis``
~~~~~~~~~~~~~~~~~~~~~~
Log messages related to :doc:`contrib/gis/index` at various points: during the
loading of external GeoSpatial libraries (GEOS, GDAL, etc.) and when reporting
errors. Each ``ERROR`` log record includes the caught exception and relevant
contextual data.
.. _django-dispatch-logger:
``django.dispatch``
~~~~~~~~~~~~~~~~~~~
This logger is used in :doc:`signals`, specifically within the
:mod:`~django.dispatch.Signal` class, to report issues when dispatching a
signal to a connected receiver. The ``ERROR`` log record includes the caught
exception as ``exc_info`` and adds the following extra context:
* ``receiver``: The name of the receiver.
* ``err``: The exception that occurred when calling the receiver.
.. _django-security-logger:
``django.security.*``

View File

@ -78,6 +78,11 @@ Minor features
* The new :meth:`.OGRGeometry.set_3d` method allows addition and removal of the
``Z`` coordinate dimension.
* :class:`~django.contrib.gis.gdal.OGRGeometry` and
:class:`~django.contrib.gis.gdal.Point` now support measured geometries
via the new :attr:`.OGRGeometry.is_measured` and :attr:`.Point.m` properties,
and the :meth:`.OGRGeometry.set_measured` method.
:mod:`django.contrib.messages`
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -348,6 +353,10 @@ Miscellaneous
* In order to improve accessibility, the admin's changelist filter is now
rendered in a ``<nav>`` tag instead of a ``<div>``.
* In order to improve accessibility, the admin's footer is now rendered in
a ``<footer>`` tag instead of a ``<div>``, and also moved below the
``<div id="main">`` element.
* :meth:`.SimpleTestCase.assertURLEqual` and
:meth:`~django.test.SimpleTestCase.assertInHTML` now add ``": "`` to the
``msg_prefix``. This is consistent with the behavior of other assertions.

View File

@ -1605,6 +1605,13 @@ class AdminViewBasicTest(AdminViewBasicTestCase):
'<main id="content-start" class="content" tabindex="-1">',
)
def test_footer(self):
response = self.client.get(reverse("admin:index"))
self.assertContains(response, '<footer id="footer">')
self.client.logout()
response = self.client.get(reverse("admin:login"))
self.assertContains(response, '<footer id="footer">')
def test_aria_describedby_for_add_and_change_links(self):
response = self.client.get(reverse("admin:index"))
tests = [

View File

@ -672,7 +672,7 @@ class OGRGeomTest(SimpleTestCase, TestDataMixin):
("PolyhedralSurface Z", 1015, False),
("TIN Z", 1016, False),
("Triangle Z", 1017, False),
("Point M", 2001, False),
("Point M", 2001, True),
("LineString M", 2002, False),
("Polygon M", 2003, False),
("MultiPoint M", 2004, False),
@ -687,7 +687,7 @@ class OGRGeomTest(SimpleTestCase, TestDataMixin):
("PolyhedralSurface M", 2015, False),
("TIN M", 2016, False),
("Triangle M", 2017, False),
("Point ZM", 3001, False),
("Point ZM", 3001, True),
("LineString ZM", 3002, False),
("Polygon ZM", 3003, False),
("MultiPoint ZM", 3004, False),
@ -812,6 +812,71 @@ class OGRGeomTest(SimpleTestCase, TestDataMixin):
self.assertEqual(g.wkt, geom)
self.assertEqual(g.wkb.hex(), wkb)
def test_measure_is_measure_and_set_measure(self):
geom = OGRGeometry("POINT (1 2 3)")
self.assertIs(geom.is_measured, False)
geom.set_measured(True)
self.assertIs(geom.is_measured, True)
self.assertEqual(geom.wkt, "POINT ZM (1 2 3 0)")
geom.set_measured(False)
self.assertIs(geom.is_measured, False)
self.assertEqual(geom.wkt, "POINT (1 2 3)")
msg = "Input to 'set_measured' must be a boolean, got 'None'"
with self.assertRaisesMessage(ValueError, msg):
geom.set_measured(None)
def test_point_m_coordinate(self):
geom = OGRGeometry("POINT ZM (1 2 3 4)")
self.assertEqual(geom.m, 4)
geom = OGRGeometry("POINT (1 2 3 4)")
self.assertEqual(geom.m, 4)
geom = OGRGeometry("POINT M (1 2 3)")
self.assertEqual(geom.m, 3)
geom = OGRGeometry("POINT Z (1 2 3)")
self.assertEqual(geom.m, None)
def test_point_m_tuple(self):
geom = OGRGeometry("POINT ZM (1 2 3 4)")
self.assertEqual(geom.tuple, (geom.x, geom.y, geom.z, geom.m))
geom = OGRGeometry("POINT M (1 2 3)")
self.assertEqual(geom.tuple, (geom.x, geom.y, geom.m))
geom = OGRGeometry("POINT Z (1 2 3)")
self.assertEqual(geom.tuple, (geom.x, geom.y, geom.z))
geom = OGRGeometry("POINT (1 2 3)")
self.assertEqual(geom.tuple, (geom.x, geom.y, geom.z))
def test_point_m_wkt_wkb(self):
wkt = "POINT ZM (1 2 3 4)"
geom = OGRGeometry(wkt)
self.assertEqual(geom.wkt, wkt)
self.assertEqual(
geom.wkb.hex(),
"01b90b0000000000000000f03f00000000000000"
"4000000000000008400000000000001040",
)
wkt = "POINT M (1 2 3)"
geom = OGRGeometry(wkt)
self.assertEqual(geom.wkt, wkt)
self.assertEqual(
geom.wkb.hex(),
"01d1070000000000000000f03f00000000000000400000000000000840",
)
def test_point_m_dimension_types(self):
geom = OGRGeometry("POINT ZM (1 2 3 4)")
self.assertEqual(geom.geom_type.name, "PointZM")
self.assertEqual(geom.geom_type.num, 3001)
geom = OGRGeometry("POINT M (1 2 3)")
self.assertEqual(geom.geom_type.name, "PointM")
self.assertEqual(geom.geom_type.num, 2001)
def test_point_m_dimension_geos(self):
"""GEOSGeometry does not yet support the M dimension."""
geom = OGRGeometry("POINT ZM (1 2 3 4)")
self.assertEqual(geom.geos.wkt, "POINT Z (1 2 3)")
geom = OGRGeometry("POINT M (1 2 3)")
self.assertEqual(geom.geos.wkt, "POINT (1 2)")
class DeprecationTests(SimpleTestCase):
def test_coord_setter_deprecation(self):

View File

@ -1,5 +1,5 @@
from django.core import mail
from django.core.management import call_command
from django.core.management import CommandError, call_command
from django.test import SimpleTestCase, override_settings
@ -46,6 +46,18 @@ class SendTestEmailManagementCommand(SimpleTestCase):
],
)
def test_missing_receivers(self):
"""
The command should complain if no receivers are given (and --admins or
--managers are not set).
"""
msg = (
"You must specify some email recipients, or pass the --managers or "
"--admin options."
)
with self.assertRaisesMessage(CommandError, msg):
call_command("sendtestemail")
def test_manager_receivers(self):
"""
The mail should be sent to the email addresses specified in