internlm/SWE-Fixer-Train-110K huggingface dataset:
Repository: liberapay/liberapay.com

Issue:
Changing donation from euro to dollar
I pledged to https://en.liberapay.com/~29539 and he now joined. My pledge was in euros and he wants dollars so I tried to stop my donation and restart it in dollars. Stopping worked but now I cannot start it again in dollars. https://en.liberapay.com/~29539/donate only gives me the euro option and on completing that form it gives the error that the users wants dollars.


Discussion:

Resolving patch:
diff --git a/liberapay/models/participant.py b/liberapay/models/participant.py
--- a/liberapay/models/participant.py
+++ b/liberapay/models/participant.py
@@ -1429,6 +1429,14 @@ def change_main_currency(self, new_currency, recorder):
                 new_currency=new_currency, old_currency=old_currency
             ), recorder=recorder_id)
 
+    def get_currency_for(self, tippee, tip):
+        if isinstance(tippee, AccountElsewhere):
+            tippee = tippee.participant
+        if tippee.accept_all_currencies:
+            return tip['amount'].currency
+        else:
+            return tippee.main_currency
+
 
     # More Random Stuff
     # =================
@@ -1882,12 +1890,9 @@ def get_giving_details(self):
                      , tippee
                      , t.ctime
                      , t.mtime
-                     , p.join_time
-                     , p.username
-                     , p.kind
+                     , p AS tippee_p
                      , t.is_funded
                      , (p.mangopay_user_id IS NOT NULL OR kind = 'group') AS is_identified
-                     , p.is_suspended
                   FROM tips t
                   JOIN participants p ON p.id = t.tippee
                  WHERE tipper = %s
diff --git a/liberapay/security/authentication.py b/liberapay/security/authentication.py
--- a/liberapay/security/authentication.py
+++ b/liberapay/security/authentication.py
@@ -22,6 +22,9 @@ class _ANON(object):
     get_tip_to = staticmethod(Participant._zero_tip_dict)
     __repr__ = lambda self: '<ANON>'
 
+    def get_currency_for(self, tippee, tip):
+        return tip['amount'].currency
+
 
 ANON = _ANON()
 
diff --git a/liberapay/utils/i18n.py b/liberapay/utils/i18n.py
--- a/liberapay/utils/i18n.py
+++ b/liberapay/utils/i18n.py
@@ -45,6 +45,10 @@ def Bold(value):
     return Wrap(value, BOLD)
 
 
+class Currency(str):
+    pass
+
+
 class Age(timedelta):
 
     def __new__(cls, *a, **kw):
@@ -263,6 +267,8 @@ def i_format(loc, s, *a, **kw):
                 c[k] = format_date(o, locale=loc)
             elif isinstance(o, Locale):
                 c[k] = loc.languages.get(o.language) or o.language.upper()
+            elif isinstance(o, Currency):
+                c[k] = loc.currencies.get(o, o)
             if wrapper:
                 c[k] = wrapper % (c[k],)
     return s.format(*a, **kw)
@@ -407,6 +413,7 @@ def add_helpers_to_context(context, loc):
         escape=_return_,  # to be overriden by renderers
         locale=loc,
         Bold=Bold,
+        Currency=Currency,
         Money=Money,
         to_age=to_age,
         _=lambda s, *a, **kw: get_text(context, kw.pop('loc', loc), s, *a, **kw),


Test patch:
Repository: liberapay/liberapay.com

Issue:
New languages fy and et don't work
The new languages [fy](https://fy.liberapay.com/) and [et](https://et.liberapay.com/) don't seem to work. It doesn't load any page on those subdomains.


Discussion:
These subdomains haven't been added in Cloudflare yet.
Alright. The pages are currently linked in the languages list so the links are visible for the visitors.
![screenshot_3](https://user-images.githubusercontent.com/7106279/34940980-0c478bdc-f9f2-11e7-98ac-8ac0b805c755.png)


@jelv your screenshot link is corrupted.
@trebmuh fixed the screenshot

Resolving patch:
diff --git a/liberapay/utils/__init__.py b/liberapay/utils/__init__.py
--- a/liberapay/utils/__init__.py
+++ b/liberapay/utils/__init__.py
@@ -14,6 +14,7 @@
 import os
 import pickle
 import re
+import socket
 
 from six import PY3
 from six.moves.urllib.parse import quote as urlquote
@@ -495,3 +496,10 @@ def render(context, allow_partial_i18n=True):
         # Fall back to English
         add_helpers_to_context(context, LOCALE_EN)
         return resource.renderers[output.media_type](context)
+
+
+def resolve(domain, port):
+    try:
+        return socket.getaddrinfo(domain, port)
+    except socket.gaierror:
+        return
diff --git a/liberapay/wireup.py b/liberapay/wireup.py
--- a/liberapay/wireup.py
+++ b/liberapay/wireup.py
@@ -41,7 +41,7 @@
 from liberapay.models.participant import Participant
 from liberapay.models.repository import Repository
 from liberapay.models import DB
-from liberapay.utils import find_files, markdown, mkdir_p
+from liberapay.utils import find_files, markdown, mkdir_p, resolve
 from liberapay.utils.currencies import MoneyBasket, get_currency_exchange_rates
 from liberapay.utils.emails import compile_email_spt
 from liberapay.utils.http_caching import asset_etag
@@ -611,10 +611,13 @@ def load_i18n(canonical_host, canonical_scheme, project_root, tell_sentry):
             continue
         l.completion = percent([m.string for m in l.catalog if m.id and not m.fuzzy], len(l.catalog))
     loc_url = canonical_scheme+'://%s.'+canonical_host
+    domain, port = (canonical_host.split(':') + [None])[:2]
+    port = int(port) if port else socket.getservbyname(canonical_scheme, 'tcp')
+    subdomains = {k: loc_url % k for k in locales if resolve(k + '.' + domain, port)}
     lang_list = sorted(
         (
             (l.completion, l.language, l.language_name.title(), loc_url % l.language)
-            for l in set(locales.values()) if l.completion
+            for l in set(locales.values()) if l.completion > 0.5
         ),
         key=lambda t: (-t[0], t[1]),
     )
@@ -645,7 +648,7 @@ def load_i18n(canonical_host, canonical_scheme, project_root, tell_sentry):
                 md = heading_re.sub(r'##\1', md)
             docs.setdefault(doc, {}).__setitem__(lang, markdown.render(md))
 
-    return {'docs': docs, 'lang_list': lang_list, 'locales': locales}
+    return {'docs': docs, 'lang_list': lang_list, 'locales': locales, 'subdomains': subdomains}
 
 
 def asset_url_generator(env, asset_url, tell_sentry, www_root):


Test patch:
Repository: liberapay/liberapay.com

Issue:
The weekly wallets check is too fast
Last night it depleted our quota of mangopay API requests.


Discussion:

Resolving patch:
diff --git a/liberapay/billing/transactions.py b/liberapay/billing/transactions.py
--- a/liberapay/billing/transactions.py
+++ b/liberapay/billing/transactions.py
@@ -1009,6 +1009,7 @@ def check_wallet_balance(w, state={}):
 
 
 def check_all_balances():
+    from liberapay.billing.payday import Payday
     from liberapay.website import website
     wallets = website.db.all("""
         SELECT *
@@ -1017,4 +1018,4 @@ def check_all_balances():
     """)
     for w in wallets:
         check_wallet_balance(w)
-        sleep(0.1)
+        sleep(max(getattr(Payday, 'transfer_delay', 0), 0.1))


Test patch:
Repository: liberapay/liberapay.com

Issue:
Ambiguous text on Organizations/Teams/Individuals pages
The Individuals page starts with "The top 18 individuals on Liberapay are:" (and likewise for Organizations). Are these all the organizations/individuals there are? If not, how can I browse/search more?

The teams page is more definitive, stating "There are 210 teams on Liberapay" and presumably lists them all.


Discussion:
To answer your questions, no, these are not all the organizations/individuals there are.

Searching can be done with the menu item, but direct browsing of individuals and organizations is not possible at the moment. Looking through the [communities](https://liberapay.com/explore/communities) is probably the next best way to browse right now.

IMHO the truncated Explore pages should be pagified and include filters.
Agree, in that case the results should be pagified.

Resolving patch:
diff --git a/liberapay/utils/__init__.py b/liberapay/utils/__init__.py
--- a/liberapay/utils/__init__.py
+++ b/liberapay/utils/__init__.py
@@ -420,14 +420,17 @@ def build_s3_object_url(key):
     return endpoint + "/" + key + "?" + querystring + "&X-Amz-Signature=" + signature
 
 
-def get_int(d, k, default=None):
+def get_int(d, k, default=None, minimum=None):
     r = d.get(k)
     if r is None:
         return default
     try:
-        return int(r)
+        r = int(r)
     except (ValueError, TypeError):
         raise Response().error(400, "`%s` value %r is not a valid integer" % (k, r))
+    if minimum is not None and r < minimum:
+        raise Response().error(400, "`%s` value %r is less than %i" % (k, r, minimum))
+    return r
 
 
 def parse_int(o, **kw):


Test patch:
Repository: liberapay/liberapay.com

Issue:
`ZeroDivisonError` in `Payday.resolve_takes()`
https://sentry.io/share/issue/4c8ac453c8994b18a7d19d7470f17499/

```
  File "liberapay/cron.py", line 61, in f
    func()
  File "liberapay/billing/payday.py", line 714, in update_cached_amounts
    cls.transfer_virtually(cursor, now)
  File "liberapay/billing/payday.py", line 322, in transfer_virtually
    Payday.transfer_takes(cursor, team_id, currency)
  File "liberapay/billing/payday.py", line 357, in transfer_takes
    transfers, leftover = Payday.resolve_takes(tips, takes, currency)
  File "liberapay/billing/payday.py", line 441, in resolve_takes
    leeway_ratio = min(delta / leeway, 1)
  File "mangopay/utils.py", line 144, in __truediv__
    raise ZeroDivisionError()
ZeroDivisionError: null
```


Discussion:

Resolving patch:
diff --git a/liberapay/billing/payday.py b/liberapay/billing/payday.py
--- a/liberapay/billing/payday.py
+++ b/liberapay/billing/payday.py
@@ -438,8 +438,12 @@ def resolve_takes(tips, takes, ref_currency):
                         for tip in tips:
                             tip.leeway = tip.full_amount - tip.amount
                     leeway = MoneyBasket(tip.leeway for tip in tips).fuzzy_sum(ref_currency)
-                    leeway_ratio = min(delta / leeway, 1)
-                    tips = sorted(tips, key=lambda tip: (-tip.weeks_to_catch_up, tip.id))
+                    if leeway == 0:
+                        # We don't actually have any leeway, give up
+                        adjust_tips = False
+                    else:
+                        leeway_ratio = min(delta / leeway, 1)
+                        tips = sorted(tips, key=lambda tip: (-tip.weeks_to_catch_up, tip.id))
         # Loop: compute the adjusted donation amounts, and do the transfers
         transfers = []
         for tip in tips:


Test patch:
Repository: liberapay/liberapay.com

Issue:
Calculation of number of weeks funded by added money seems wrong
When adding money ![image](https://user-images.githubusercontent.com/6146483/38662377-60465098-3e34-11e8-9d27-ebc65a1124b2.png)

The values calculated by the formula `amount_added/donation_per_week` seem wrong:
![image](https://user-images.githubusercontent.com/6146483/38662270-0cc83288-3e34-11e8-8d54-c241616ba88f.png)

when my `donation_per_week` amount is 
![image](https://user-images.githubusercontent.com/6146483/38662279-1675b7ec-3e34-11e8-839c-4822b183e144.png)



Discussion:
It looks like both donations and pledges are counted in this formula.
Right.

It is consistent with pledges:

![image](https://user-images.githubusercontent.com/6146483/38664942-5934dba6-3e3b-11e8-8223-db5867689b67.png)



Resolving patch:
diff --git a/liberapay/models/participant.py b/liberapay/models/participant.py
--- a/liberapay/models/participant.py
+++ b/liberapay/models/participant.py
@@ -1732,8 +1732,11 @@ def get_giving_in(self, currency):
         return self.db.one("""
             SELECT sum(t.amount)
               FROM current_tips t
+              JOIN participants p ON p.id = t.tippee
              WHERE t.tipper = %s
                AND t.amount::currency = %s
+               AND p.status = 'active'
+               AND (p.goal IS NULL OR p.goal >= 0)
         """, (self.id, currency)) or ZERO[currency]
 
     def get_receiving_in(self, currency, cursor=None):


Test patch:
Repository: liberapay/liberapay.com

Issue:
Restrict cookies to same-site requests
[Support for Same-Site cookies has landed in Firefox 60](https://blog.mozilla.org/security/2018/04/24/same-site-cookies-in-firefox-60/). We should add `SameSite=lax` to all our cookies as an additional protection against CSRF. Bonus: this should speed up widgets included in third-party websites, and enforce privacy by preventing the tracking of users through those widgets.


Discussion:

Resolving patch:
diff --git a/liberapay/main.py b/liberapay/main.py
--- a/liberapay/main.py
+++ b/liberapay/main.py
@@ -171,6 +171,14 @@ def _assert(x):
 ]
 
 
+# Monkey patch python's stdlib
+# ============================
+
+from six.moves.http_cookies import Morsel
+
+Morsel._reserved[str('samesite')] = str('SameSite')
+
+
 # Monkey patch aspen and pando
 # ============================
 
diff --git a/liberapay/utils/__init__.py b/liberapay/utils/__init__.py
--- a/liberapay/utils/__init__.py
+++ b/liberapay/utils/__init__.py
@@ -286,7 +286,7 @@ def ensure_str(s):
     return s.decode('ascii') if isinstance(s, bytes) else s.encode('ascii')
 
 
-def set_cookie(cookies, key, value, expires=None, httponly=True, path='/'):
+def set_cookie(cookies, key, value, expires=None, httponly=True, path='/', samesite='lax'):
     key = ensure_str(key)
     cookies[key] = ensure_str(value)
     cookie = cookies[key]
@@ -300,6 +300,8 @@ def set_cookie(cookies, key, value, expires=None, httponly=True, path='/'):
         cookie[str('httponly')] = True
     if path:
         cookie[str('path')] = ensure_str(path)
+    if samesite:
+        cookie[str('samesite')] = ensure_str(samesite)
     if website.cookie_domain:
         cookie[str('domain')] = ensure_str(website.cookie_domain)
     if website.canonical_scheme == 'https':


Test patch:
diff --git a/tests/py/test_state_chain.py b/tests/py/test_state_chain.py
--- a/tests/py/test_state_chain.py
+++ b/tests/py/test_state_chain.py
@@ -94,6 +94,7 @@ def test_csrf_cookie_properties(self):
         assert cookie[str('expires')][-4:] == str(' GMT')
         assert cookie[str('path')] == str('/')
         assert cookie[str('secure')] is True
+        assert cookie[str('samesite')] == str('lax')
 
 
 class Tests2(Harness):
Repository: liberapay/liberapay.com

Issue:
Support avatars from Gitlab
Quite a number of open-source projects are hosted on Gitlab, including mine.

With Libavatar [shutting down](https://blog.libravatar.org/posts/Libravatar.org_is_shutting_down_on_2018-09-01/), it'd be nice to have an alternative that doesn't require creating an account on a proprietary service. (While Mastodon isn't proprietary, it's still an unnecessary extra account to take care of.)


Discussion:

Resolving patch:
diff --git a/liberapay/constants.py b/liberapay/constants.py
--- a/liberapay/constants.py
+++ b/liberapay/constants.py
@@ -57,7 +57,9 @@ def with_vat(self):
                                 "-_.")
 
 AVATAR_QUERY = '?s=160&default=retro'
-AVATAR_SOURCES = 'libravatar bitbucket facebook github google mastodon twitter'.split()
+AVATAR_SOURCES = (
+    'libravatar bitbucket facebook github gitlab google mastodon twitch twitter youtube'
+).split()
 
 BIRTHDAY = date(2015, 5, 22)
 


Test patch:
Repository: liberapay/liberapay.com

Issue:
Postal Code pattern is invalid for Portugal
I'm unable to add money via direct debit because the postal code verification is invalid for Portuguese postal codes [0]. When inspecting the input, I see the pattern is `[a-zA-Z0-9]+`, but the postal codes here are `[0-9]{4}\-[0-9]{3}`. Just adding the hyphen should cover it and also more countries that may have them.

[0] https://en.wikipedia.org/wiki/Postal_codes_in_Portugal


Discussion:

Resolving patch:
diff --git a/liberapay/models/participant.py b/liberapay/models/participant.py
--- a/liberapay/models/participant.py
+++ b/liberapay/models/participant.py
@@ -1025,7 +1025,8 @@ def render(t, context):
                     context['body'] = markdown.render(context['body']).strip()
                 return spt[t].render(context).strip()
         else:
-            base_spt = context.get('base_spt', 'base')
+            base_spt = None if spt_name.startswith('once/') else 'base'
+            base_spt = context.get('base_spt', base_spt)
             base_spt = website.emails[base_spt] if base_spt else None
             bodies = {}
             def render(t, context):


Test patch:
Repository: liberapay/liberapay.com

Issue:
Not receiving one-time login email
I created an account but am now locked out since I am not receiving the one-time login emails to login to the site.  I've tried this several times, been locked out for a day, and tried again the next day, but still no luck.


Discussion:
Did you look receive the confirmation email? Did you look in the spam folder?
I looked *carefully* in the spam folder each time and did not see a confirmation email there.
I emailed support from the email that I used to register to confirm its validity.

Resolving patch:
diff --git a/liberapay/wireup.py b/liberapay/wireup.py
--- a/liberapay/wireup.py
+++ b/liberapay/wireup.py
@@ -23,7 +23,7 @@
 from babel.numbers import parse_pattern
 import boto3
 from environment import Environment, is_yesish
-from mailshake import DummyMailer, SMTPMailer
+from mailshake import AmazonSESMailer, DummyMailer, SMTPMailer
 from mangopay.utils import Money
 import psycopg2
 from psycopg2.extensions import adapt, AsIs, new_type, register_adapter, register_type
@@ -230,6 +230,7 @@ class AppConf(object):
         s3_secret_key=str,
         s3_region=str,
         s3_payday_logs_bucket=str,
+        ses_region=str,
         send_newsletters_every=int,
         show_sandbox_warning=bool,
         socket_timeout=float,
@@ -318,7 +319,7 @@ def parse_network(net):
         return {'trusted_proxies': []}
 
 
-def mail(app_conf, project_root='.'):
+def mail(app_conf, env, project_root='.'):
     if not app_conf:
         return
     smtp_conf = {
@@ -326,7 +327,15 @@ def mail(app_conf, project_root='.'):
     }
     if smtp_conf:
         smtp_conf.setdefault('timeout', app_conf.socket_timeout)
-    mailer = SMTPMailer(**smtp_conf) if smtp_conf else DummyMailer()
+    if app_conf.ses_region:
+        mailer = AmazonSESMailer(
+            env.aws_access_key_id, env.aws_secret_access_key,
+            region=app_conf.ses_region
+        )
+    elif smtp_conf:
+        mailer = SMTPMailer(**smtp_conf)
+    else:
+        mailer = DummyMailer()
     emails = {}
     emails_dir = project_root+'/emails/'
     i = len(emails_dir)


Test patch:
Repository: liberapay/liberapay.com

Issue:
Paypal email is not verified. Although I verified it.
I see you added Paypal as a payment option which is great. However when I add my paypal email - which is different from liberapay email - it still says it is not verified although I received an email and clicked "verify". Is this a bug?


Discussion:

Resolving patch:
diff --git a/liberapay/payin/paypal.py b/liberapay/payin/paypal.py
--- a/liberapay/payin/paypal.py
+++ b/liberapay/payin/paypal.py
@@ -107,7 +107,7 @@ def create_payment(db, payin, payer, return_url, state):
                     "price": str(pt.unit_amount.amount),
                     "currency": pt.unit_amount.currency
                 }]
-            }
+            } if pt.n_units >= 1 else {}
         } for pt in transfers],
         "redirect_urls": {
             "return_url": return_url,
@@ -163,9 +163,11 @@ def execute_payment(db, payin, payer_id):
             pt_remote_id = sale['id']
             pt_status = SALE_STATES_MAP[sale['state']]
             pt_error = sale.get('reason_code')
-            pt_fee = Money(sale['transaction_fee']['value'], sale['transaction_fee']['currency'])
+            pt_fee = sale.get('transaction_fee')
+            if pt_fee:
+                pt_fee = Money(pt_fee['value'], pt_fee['currency'])
             charge_amount = Money(sale['amount']['total'], sale['amount']['currency'])
-            net_amount = charge_amount - pt_fee
+            net_amount = charge_amount - (pt_fee or 0)
             update_payin_transfer(
                 db, pt_id, pt_remote_id, pt_status, pt_error,
                 amount=net_amount, fee=pt_fee


Test patch:
Repository: liberapay/liberapay.com

Issue:
Bug during payment modification
I try to donate to this account: https://liberapay.com/lowtechlab/ after a previous promise on the twitter account.

lowtechlab created its account on the plateform but if I see that I donate to it, the actual number of mecene is still 0.

I tried to change the amount since I know that with the new system we need to do a payment in advance but I had a 500 error with the following error code: `fc677c3e6c54434ba77bcf1eac628a18`


Discussion:

Resolving patch:
diff --git a/liberapay/utils/currencies.py b/liberapay/utils/currencies.py
--- a/liberapay/utils/currencies.py
+++ b/liberapay/utils/currencies.py
@@ -51,7 +51,7 @@ def _Money_init(self, amount=Decimal('0'), currency=None, rounding=None):
 
 def _Money_eq(self, other):
     if isinstance(other, self.__class__):
-        return self.__dict__ == other.__dict__
+        return self.amount == other.amount and self.currency == other.currency
     if isinstance(other, (Decimal, Number)):
         return self.amount == other
     if isinstance(other, MoneyBasket):


Test patch:
diff --git a/tests/py/test_currencies.py b/tests/py/test_currencies.py
--- a/tests/py/test_currencies.py
+++ b/tests/py/test_currencies.py
@@ -134,10 +134,34 @@ def test_basket_sum(self):
         expected = MoneyBasket()
         actual = self.db.one("SELECT basket_sum(x) FROM unnest(NULL::currency_amount[]) x")
         assert expected == actual
+        actual = self.db.one("SELECT basket_sum(x) FROM unnest(ARRAY[NULL]::currency_amount[]) x")
+        assert expected == actual
         # Non-empty sum
         expected = MoneyBasket(EUR=D('0.33'), USD=D('0.77'))
-        actual = self.db.one("SELECT basket_sum(x) FROM unnest(%s) x", (list(expected),))
+        actual = self.db.one("SELECT basket_sum(x) FROM unnest(%s) x", (list(expected) + [None],))
+        assert expected == actual
+
+    def test_sums(self):
+        # Empty sum
+        actual = self.db.one("SELECT sum(x) FROM unnest(NULL::currency_amount[]) x")
+        assert actual is None
+        actual = self.db.one("SELECT sum(x) FROM unnest(ARRAY[NULL]::currency_amount[]) x")
+        assert actual is None
+        # Empty fuzzy sum
+        actual = self.db.one("SELECT sum(x, 'EUR') FROM unnest(NULL::currency_amount[]) x")
+        assert actual is None
+        actual = self.db.one("SELECT sum(x, 'EUR') FROM unnest(ARRAY[NULL]::currency_amount[]) x")
+        assert actual is None
+        # Single-currency sum
+        amounts = [JPY('133'), JPY('977')]
+        expected = sum(amounts)
+        actual = self.db.one("SELECT sum(x, 'JPY') FROM unnest(%s) x", (amounts + [None],))
         assert expected == actual
+        # Fuzzy sum
+        amounts = [EUR('0.50'), USD('1.20')]
+        expected = MoneyBasket(*amounts).fuzzy_sum('EUR')
+        actual = self.db.one("SELECT sum(x, 'EUR') FROM unnest(%s) x", (amounts + [None],))
+        assert expected == actual, (expected.__dict__, actual.__dict__)
 
 
 class TestCurrenciesSimplate(Harness):