Repository: geopandas/geopandas

Issue:
Add a Code of Conduct for the GeoPandas project
I propose to adopt a Code of Conduct for the GeoPandas project, and more specifically based on the Contributor Covenant.

---

I *think* we never had a situation up to now where we would have needed to act upon one, but, you never need to wait until it is too late and it also the signal you give with it to community members and newcomers.
(it is also mentioned in https://github.com/geopandas/geopandas/community as recommended community standard, and in addition, it is also required to apply for NumFOCUS affiliated project)

I propose to add the Code of Conduct developed by the Contributor Covenant project (https://www.contributor-covenant.org/). It is also used by pandas, xarray, dask, ... 
But there are also some alternatives, eg the one of [Python](https://www.python.org/psf/codeofconduct/), [Jupyter](https://github.com/jupyter/governance/blob/master/conduct/code_of_conduct.md), ..

The main question is how to handle reports. The template expects you to fill in an email address. For pandas, we created a specific private google groups (that a "subcommittee" is subscribed to) for this. And I think in Dask they are doing the same, in addition of providing a form to report something anonymously (https://github.com/dask/governance/pull/10). 
We can do the same for GeoPandas.

cc @geopandas/collaborators @martinfleis @ljwolf 

Discussion:
ljwolf: This is real cool; excited to see this adopted!
jorisvandenbossche: > decide who will be on the Code of Conduct committee.

So I asked Hannah (@story645), and she is willing to be on the committee. 
Martin, would you like to be part of it as well?

I can also be on the committee (although I always find it doesn't feel fully good that the most active people (i.e. Martin and me) are all on the committee, since they are most likely to be already involved in some way in the issue being reported)
martinfleis: @jorisvandenbossche I have no problem being part of the committee.

I agree with the issue of having the most active people on the board. If we should choose between us, does not make more sense to have there you as a maintainer?
jorisvandenbossche: Let's go with us both for now. 

I created the geopandas-conduct@googlegroups.com mailing address and a form: https://docs.google.com/forms/d/e/1FAIpQLSd8Tbi2zNl1i2N9COX0yavHEqTGFIPQ1_cLcy1A3JgVc1OrAQ/viewform?usp=sf_link (and normally we should get email notifications for that form as well).



Patch:
diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md
new file mode 100644
index 00000000..47d20aa1
--- /dev/null
+++ b/CODE_OF_CONDUCT.md
@@ -0,0 +1,133 @@
+# GeoPandas Project Code of Conduct
+
+Behind the GeoPandas Project is an engaged and respectful community made up of people
+from all over the world and with a wide range of backgrounds.
+Naturally, this implies diversity of ideas and perspectives on often complex
+problems. Disagreement and healthy discussion of conflicting viewpoints is
+welcome: the best solutions to hard problems rarely come from a single angle.
+But disagreement is not an excuse for aggression: humans tend to take
+disagreement personally and easily drift into behavior that ultimately degrades
+a community. This is particularly acute with online communication across
+language and cultural gaps, where many cues of human behavior are unavailable.
+We are outlining here a set of principles and processes to support a
+healthy community in the face of these challenges.
+
+Fundamentally, we are committed to fostering a productive, harassment-free
+environment for everyone. Rather than considering this code an exhaustive list
+of things that you can’t do, take it in the spirit it is intended - a guide to
+make it easier to enrich all of us and the communities in which we participate.
+
+Importantly: as a member of our community, *you are also a steward of these
+values*.  Not all problems need to be resolved via formal processes, and often
+a quick, friendly but clear word on an online forum or in person can help
+resolve a misunderstanding and de-escalate things.
+
+However, sometimes these informal processes may be inadequate: they fail to
+work, there is urgency or risk to someone, nobody is intervening publicly and
+you don't feel comfortable speaking in public, etc.  For these or other
+reasons, structured follow-up may be necessary and here we provide the means
+for that: we welcome reports by emailing
+[*geopandas-conduct@googlegroups.com*](mailto:geopandas-conduct@googlegroups.com)
+or by filling out
+[this form](https://docs.google.com/forms/d/e/1FAIpQLSd8Tbi2zNl1i2N9COX0yavHEqTGFIPQ1_cLcy1A3JgVc1OrAQ/viewform).
+
+This code applies equally to founders, developers, mentors and new community
+members, in all spaces managed by the GeoPandas Project. This
+includes the mailing lists, our GitHub organization, our chat room, in-person
+events, and any other forums created by the project team. In addition,
+violations of this code outside these spaces may affect a person's ability to
+participate within them.
+
+By embracing the following principles, guidelines and actions to follow or
+avoid, you will help us make the GeoPandas Project a welcoming and productive community. Feel
+free to contact the Code of Conduct Committee at
+[*geopandas-conduct@googlegroups.com*](mailto:geopandas-conduct@googlegroups.com)  with any questions.
+
+
+1. **Be friendly and patient**.
+
+2. **Be welcoming**. We strive to be a community that welcomes and supports
+   people of all backgrounds and identities. This includes, but is not limited
+   to, members of any race, ethnicity, culture, national origin, color,
+   immigration status, social and economic class, educational level, sex, sexual
+   orientation, gender identity and expression, age, physical appearance, family
+   status, technological or professional choices, academic
+   discipline, religion, mental ability, and physical ability.
+
+3. **Be considerate**. Your work will be used by other people, and you in turn
+   will depend on the work of others. Any decision you take will affect users
+   and colleagues, and you should take those consequences into account when
+   making decisions. Remember that we're a world-wide community. You may be
+   communicating with someone with a different primary language or cultural
+   background.
+
+4. **Be respectful**. Not all of us will agree all the time, but disagreement is
+   no excuse for poor behavior or poor manners. We might all experience some
+   frustration now and then, but we cannot allow that frustration to turn into a
+   personal attack. It’s important to remember that a community where people
+   feel uncomfortable or threatened is not a productive one.
+
+5. **Be careful in the words that you choose**. Be kind to others. Do not insult
+   or put down other community members. Harassment and other exclusionary
+   behavior are not acceptable. This includes, but is not limited to:
+   * Violent threats or violent language directed against another person
+   * Discriminatory jokes and language
+   * Posting sexually explicit or violent material
+   * Posting (or threatening to post) other people's personally identifying
+     information ("doxing")
+   * Personal insults, especially those using racist, sexist, and xenophobic terms
+   * Unwelcome sexual attention
+   * Advocating for, or encouraging, any of the above behavior
+   * Repeated harassment of others. In general, if someone asks you to stop,
+     then stop
+
+6. **Moderate your expectations**. Please respect that community members choose
+   how they spend their time in the project. A thoughtful question about your
+   expectations is preferable to demands for another person's time.
+
+7. **When we disagree, try to understand why**. Disagreements, both social and
+   technical, happen all the time and the GeoPandas Project is no exception.  Try to
+   understand where others are coming from, as seeing a question from their
+   viewpoint may help find a new path forward.  And don’t forget that it is
+   human to err: blaming each other doesn’t get us anywhere, while we can learn
+   from mistakes to find better solutions.
+
+8. **A simple apology can go a long way**. It can often de-escalate a situation,
+   and telling someone that you are sorry is an act of empathy that doesn’t
+   automatically imply an admission of guilt.
+
+
+## Reporting
+
+If you believe someone is violating the code of conduct, please report this in
+a timely manner. Code of conduct violations reduce the value of the community
+for everyone and we take them seriously.
+
+You can file a report by emailing
+[*geopandas-conduct@googlegroups.com*](mailto:geopandas-conduct@googlegroups.com) or by filing out
+[this form](https://docs.google.com/forms/d/e/1FAIpQLSd8Tbi2zNl1i2N9COX0yavHEqTGFIPQ1_cLcy1A3JgVc1OrAQ/viewform).
+
+The online form gives you the option to keep your report anonymous or request
+that we follow up with you directly. While we cannot follow up on an anonymous
+report, we will take appropriate action.
+
+Messages sent to the e-mail address or through the form will be sent
+only to the Code of Conduct Committee, which currently consists of:
+
+* Hannah Aizenman
+* Joris Van den Bossche
+* Martin Fleischmann
+
+
+## Enforcement
+
+Enforcement procedures within the GeoPandas Project follow Project Jupyter's
+[*Enforcement Manual*](https://github.com/jupyter/governance/blob/master/conduct/enforcement.md). For information on enforcement, please view the [original manual](https://github.com/jupyter/governance/blob/master/conduct/enforcement.md).
+
+Original text courtesy of the [*Speak
+Up!*](http://web.archive.org/web/20141109123859/http://speakup.io/coc.html),
+[*Django*](https://www.djangoproject.com/conduct) and [*Jupyter*](https://github.com/jupyter/governance/blob/master/conduct/code_of_conduct.md) Projects,
+modified by the GeoPandas Project. We are grateful to those projects for contributing these materials under open licensing terms for us to easily reuse.
+
+All content on this page is licensed under a [*Creative Commons
+Attribution*](http://creativecommons.org/licenses/by/3.0/) license.
diff --git a/doc/source/code_of_conduct.rst b/doc/source/code_of_conduct.rst
new file mode 100644
index 00000000..e80db517
--- /dev/null
+++ b/doc/source/code_of_conduct.rst
@@ -0,0 +1,135 @@
+GeoPandas Project Code of Conduct
+=================================
+
+Behind the GeoPandas Project is an engaged and respectful community made up of
+people from all over the world and with a wide range of backgrounds.
+Naturally, this implies diversity of ideas and perspectives on often
+complex problems. Disagreement and healthy discussion of conflicting
+viewpoints is welcome: the best solutions to hard problems rarely come from a single
+angle. But disagreement is not an excuse for aggression: humans tend to take
+disagreement personally and easily drift into behavior that ultimately
+degrades a community. This is particularly acute with online communication
+across language and cultural gaps, where many cues of human behavior are
+unavailable. We are outlining here a set of principles and processes to support a
+healthy community in the face of these challenges.
+
+Fundamentally, we are committed to fostering a productive, harassment-free
+environment for everyone. Rather than considering this code an exhaustive list
+of things that you can’t do, take it in the spirit it is intended - a guide to
+make it easier to enrich all of us and the communities in which we participate.
+
+Importantly: as a member of our community, *you are also a steward of these
+values*. Not all problems need to be resolved via formal processes, and often
+a quick, friendly but clear word on an online forum or in person can help
+resolve a misunderstanding and de-escalate things.
+
+However, sometimes these informal processes may be inadequate: they fail to
+work, there is urgency or risk to someone, nobody is intervening publicly and
+you don't feel comfortable speaking in public, etc. For these or other
+reasons, structured follow-up may be necessary and here we provide the means
+for that: we welcome reports by emailing
+`geopandas-conduct@googlegroups.com <mailto:geopandas-conduct@googlegroups.com>`__ or by filling out `this
+form <https://docs.google.com/forms/d/e/1FAIpQLSd8Tbi2zNl1i2N9COX0yavHEqTGFIPQ1_cLcy1A3JgVc1OrAQ/viewform>`__.
+
+This code applies equally to founders, developers, mentors and new community
+members, in all spaces managed by the GeoPandas Project. This
+includes the mailing lists, our GitHub organization, our chat room, in-person
+events, and any other forums created by the project team. In addition,
+violations of this code outside these spaces may affect a person's ability to
+participate within them.
+
+By embracing the following principles, guidelines and actions to follow or
+avoid, you will help us make Jupyter a welcoming and productive community. Feel
+free to contact the Code of Conduct Committee at
+`geopandas-conduct@googlegroups.com <mailto:geopandas-conduct@googlegroups.com>`__ with any questions.
+
+1. **Be friendly and patient**.
+
+2. **Be welcoming**. We strive to be a community that welcomes and supports
+   people of all backgrounds and identities. This includes, but is not limited
+   to, members of any race, ethnicity, culture, national origin, color,
+   immigration status, social and economic class, educational level, sex, sexual
+   orientation, gender identity and expression, age, physical appearance, family
+   status, technological or professional choices, academic
+   discipline, religion, mental ability, and physical ability.
+
+3. **Be considerate**. Your work will be used by other people, and you in turn
+   will depend on the work of others. Any decision you take will affect users
+   and colleagues, and you should take those consequences into account when
+   making decisions. Remember that we're a world-wide community. You may be
+   communicating with someone with a different primary language or cultural
+   background.
+
+4. **Be respectful**. Not all of us will agree all the time, but disagreement is
+   no excuse for poor behavior or poor manners. We might all experience some
+   frustration now and then, but we cannot allow that frustration to turn into a
+   personal attack. It’s important to remember that a community where people
+   feel uncomfortable or threatened is not a productive one.
+
+5. **Be careful in the words that you choose**. Be kind to others. Do not insult
+   or put down other community members. Harassment and other exclusionary
+   behavior are not acceptable. This includes, but is not limited to:
+
+   -  Violent threats or violent language directed against another person
+   -  Discriminatory jokes and language
+   -  Posting sexually explicit or violent material
+   -  Posting (or threatening to post) other people's personally identifying information ("doxing")
+   -  Personal insults, especially those using racist, sexist, and xenophobic terms
+   -  Unwelcome sexual attention
+   -  Advocating for, or encouraging, any of the above behavior
+   -  Repeated harassment of others. In general, if someone asks you to stop, then stop
+
+6. **Moderate your expectations**. Please respect that community members choose
+   how they spend their time in the project. A thoughtful question about your
+   expectations is preferable to demands for another person's time.
+
+7. **When we disagree, try to understand why**. Disagreements, both social and
+   technical, happen all the time and the GeoPandas Project is no exception. Try to
+   understand where others are coming from, as seeing a question from their
+   viewpoint may help find a new path forward. And don’t forget that it is
+   human to err: blaming each other doesn’t get us anywhere, while we can learn
+   from mistakes to find better solutions.
+
+8. **A simple apology can go a long way**. It can often de-escalate a situation,
+   and telling someone that you are sorry is an act of empathy that doesn’t
+    automatically imply an admission of guilt.
+
+Reporting
+---------
+
+If you believe someone is violating the code of conduct, please report this in
+a timely manner. Code of conduct violations reduce the value of the community
+for everyone and we take them seriously.
+
+You can file a report by emailing
+`geopandas-conduct@googlegroups.com <mailto:geopandas-conduct@googlegroups.com>`__ or by filing out
+`this form <https://docs.google.com/forms/d/e/1FAIpQLSd8Tbi2zNl1i2N9COX0yavHEqTGFIPQ1_cLcy1A3JgVc1OrAQ/viewform>`__.
+
+The online form gives you the option to keep your report anonymous or request
+that we follow up with you directly. While we cannot follow up on an anonymous
+report, we will take appropriate action.
+
+Messages sent to the e-mail address or through the form will be sent
+only to the Code of Conduct Committee, which currently consists of:
+
+- Hannah Aizenman
+- Joris Van den Bossche
+- Martin Fleischmann
+
+Enforcement
+-----------
+
+Enforcement procedures within the GeoPandas Project follow Project Jupyter's `Enforcement
+Manual <https://github.com/jupyter/governance/blob/master/conduct/enforcement.md>`__.
+For information on enforcement, please view the `original
+manual <https://github.com/jupyter/governance/blob/master/conduct/enforcement.md>`__.
+
+Original text courtesy of the `Speak
+Up! <http://web.archive.org/web/20141109123859/http://speakup.io/coc.html>`__,
+`Django <https://www.djangoproject.com/conduct>`__ and
+`Jupyter <https://github.com/jupyter/governance/blob/master/conduct/code_of_conduct.md>`__
+Projects, modified by the GeoPandas Project. We are grateful to those projects for
+contributing these materials under open licensing terms for us to easily reuse.
+
+All content on this page is licensed under a `Creative Commons
+Attribution <http://creativecommons.org/licenses/by/3.0/>`__ license.
diff --git a/doc/source/index.rst b/doc/source/index.rst
index 504ca09b..63f009fd 100644
--- a/doc/source/index.rst
+++ b/doc/source/index.rst
@@ -59,6 +59,7 @@ such as PostGIS.
   :caption: Developer
 
   Contributing to GeoPandas <contributing>
+  Code of Conduct <code_of_conduct>
 
 
 Get in touch
diff --git a/geopandas/io/file.py b/geopandas/io/file.py
index 0eaa937b..1c9bbdb8 100644
--- a/geopandas/io/file.py
+++ b/geopandas/io/file.py
@@ -129,7 +129,10 @@ def read_file(filename, bbox=None, mask=None, rows=None, **kwargs):
     return gdf
 
 
-def to_file(df, filename, driver="ESRI Shapefile", schema=None, index=None, **kwargs):
+def to_file(
+    df, filename, driver="ESRI Shapefile", schema=None, index=None, mode="w", **kwargs
+):
+
     """
     Write this GeoDataFrame to an OGR data source
 
@@ -156,6 +159,11 @@ def to_file(df, filename, driver="ESRI Shapefile", schema=None, index=None, **kw
 
         .. versionadded:: 0.7
             Previously the index was not written.
+    mode : string, default 'w'
+        The write mode, 'w' to overwrite the existing file and 'a' to append.
+        Not all drivers support appending. The drivers that support appending
+        are listed in fiona.supported_drivers or
+        https://github.com/Toblerity/Fiona/blob/master/fiona/drvsupport.py
 
     The *kwargs* are passed to fiona.open and can be used to write
     to multi-layer data, store data within archives (zip files), etc.
@@ -188,7 +196,7 @@ def to_file(df, filename, driver="ESRI Shapefile", schema=None, index=None, **kw
         elif df.crs:
             crs_wkt = df.crs.to_wkt("WKT1_GDAL")
         with fiona.open(
-            filename, "w", driver=driver, crs_wkt=crs_wkt, schema=schema, **kwargs
+            filename, mode=mode, driver=driver, crs_wkt=crs_wkt, schema=schema, **kwargs
         ) as colxn:
             colxn.writerecords(df.iterfeatures())
 
diff --git a/geopandas/tools/clip.py b/geopandas/tools/clip.py
index da022b8e..bf74e837 100644
--- a/geopandas/tools/clip.py
+++ b/geopandas/tools/clip.py
@@ -152,7 +152,11 @@ def clip(gdf, mask, keep_geom_type=False):
         ((box_mask[0] <= box_gdf[2]) and (box_gdf[0] <= box_mask[2]))
         and ((box_mask[1] <= box_gdf[3]) and (box_gdf[1] <= box_mask[3]))
     ):
-        return GeoDataFrame(columns=gdf.columns, crs=gdf.crs)
+        return (
+            GeoDataFrame(columns=gdf.columns, crs=gdf.crs)
+            if isinstance(gdf, GeoDataFrame)
+            else GeoSeries(crs=gdf.crs)
+        )
 
     if isinstance(mask, (GeoDataFrame, GeoSeries)):
         poly = mask.geometry.unary_union


Test patch:
diff --git a/geopandas/io/tests/test_file.py b/geopandas/io/tests/test_file.py
index b2301b43..1bba3d85 100644
--- a/geopandas/io/tests/test_file.py
+++ b/geopandas/io/tests/test_file.py
@@ -230,6 +230,36 @@ def test_to_file_schema(tmpdir, df_nybb):
     assert result_schema == schema
 
 
+@pytest.mark.parametrize("driver,ext", driver_ext_pairs)
+def test_append_file(tmpdir, df_nybb, df_null, driver, ext):
+    """ Test to_file with append mode and from_file """
+    from fiona import supported_drivers
+
+    if "a" not in supported_drivers[driver]:
+        return None
+
+    tempfilename = os.path.join(str(tmpdir), "boros." + ext)
+    df_nybb.to_file(tempfilename, driver=driver)
+    df_nybb.to_file(tempfilename, mode="a", driver=driver)
+    # Read layer back in
+    df = GeoDataFrame.from_file(tempfilename)
+    assert "geometry" in df
+    assert len(df) == (5 * 2)
+    expected = pd.concat([df_nybb] * 2, ignore_index=True)
+    assert_geodataframe_equal(df, expected)
+
+    # Write layer with null geometry out to file
+    tempfilename = os.path.join(str(tmpdir), "null_geom." + ext)
+    df_null.to_file(tempfilename, driver=driver)
+    df_null.to_file(tempfilename, mode="a", driver=driver)
+    # Read layer back in
+    df = GeoDataFrame.from_file(tempfilename)
+    assert "geometry" in df
+    assert len(df) == (2 * 2)
+    expected = pd.concat([df_null] * 2, ignore_index=True)
+    assert_geodataframe_equal(df, expected)
+
+
 # -----------------------------------------------------------------------------
 # read_file tests
 # -----------------------------------------------------------------------------
diff --git a/geopandas/tools/tests/test_clip.py b/geopandas/tools/tests/test_clip.py
index 64aea513..ffacf656 100644
--- a/geopandas/tools/tests/test_clip.py
+++ b/geopandas/tools/tests/test_clip.py
@@ -9,7 +9,7 @@ from shapely.geometry import Polygon, Point, LineString, LinearRing, GeometryCol
 
 import geopandas
 from geopandas import GeoDataFrame, GeoSeries, clip
-from geopandas.testing import assert_geodataframe_equal
+from geopandas.testing import assert_geodataframe_equal, assert_geoseries_equal
 
 import pytest
 
@@ -159,7 +159,7 @@ def test_returns_series(point_gdf, single_rectangle_gdf):
 
 
 def test_non_overlapping_geoms():
-    """Test that a bounding box returns error if the extents don't overlap"""
+    """Test that a bounding box returns empty if the extents don't overlap"""
     unit_box = Polygon([(0, 0), (0, 1), (1, 1), (1, 0), (0, 0)])
     unit_gdf = GeoDataFrame([1], geometry=[unit_box], crs="EPSG:4326")
     non_overlapping_gdf = unit_gdf.copy()
@@ -170,6 +170,8 @@ def test_non_overlapping_geoms():
     assert_geodataframe_equal(
         out, GeoDataFrame(columns=unit_gdf.columns, crs=unit_gdf.crs)
     )
+    out2 = clip(unit_gdf.geometry, non_overlapping_gdf)
+    assert_geoseries_equal(out2, GeoSeries(crs=unit_gdf.crs))
 
 
 def test_clip_points(point_gdf, single_rectangle_gdf):