GHC 2017-01-18

2 comments.

, https://git.io/vMMYn in yadayada/acd_cli
Regression in 4ee6f55: get_conflicting_node fails to recognize conflict when filename contains non-ASCII uppercase character
============================================================================================================================

Since 4ee6f55, `get_conflicting_node` has been executing

```py
c.execute(CONFLICTING_NODE_SQL, [parent_id, name.lower()])
```

where

```py
CONFLICTING_NODE_SQL = """SELECT n.*, f.* FROM nodes n
                  JOIN parentage p ON n.id = p.child
                  LEFT OUTER JOIN files f ON n.id = f.id
                  WHERE p.parent = (?) AND LOWER(name) = (?) AND status = 'AVAILABLE'
                  ORDER BY n.name"""
```

Note the discrepancy in lowercase conversion here: SQLite's `lower` only lowers ASCII characters unless the ICU extension is loaded ([ref](https://www.sqlite.org/lang_corefunc.html#lower)) whereas Python's `str.lower` works on the full Unicode range.

For now I've worked around the issue by crippling lower on the Python side. Patch:

```diff
diff --git a/acdcli/cache/query.py b/acdcli/cache/query.py
index 469b953..a026866 100644
--- a/acdcli/cache/query.py
+++ b/acdcli/cache/query.py
@@ -1,4 +1,5 @@
 import logging
+import string
 from datetime import datetime
 from .cursors import cursor
 
@@ -150,10 +151,20 @@ class QueryMixin(object):
     def get_root_node(self):
         return self.get_node(self.root_id)
 
+    @staticmethod
+    def asciilower(name: str):
+        '''Returns a copy of name with all ASCII characters converted to lower case.
+
+        For compatibility with SQLite lower(X) (with ICU extension).
+        See https://www.sqlite.org/lang_corefunc.html#lower.
+        '''
+        table = str.maketrans(string.ascii_uppercase, string.ascii_lowercase)
+        return name.translate(table)
+
     def get_conflicting_node(self, name: str, parent_id: str):
         """Finds conflicting node in folder specified by *parent_id*, if one exists."""
         with cursor(self._conn) as c:
-            c.execute(CONFLICTING_NODE_SQL, [parent_id, name.lower()])
+            c.execute(CONFLICTING_NODE_SQL, [parent_id, self.asciilower(name)])
             r = c.fetchone()
             if r:
                 return Node(r)
```

This is not ideal, though, because according to testing the case insensitivity on the ACD side applies to more than just ASCII; for instance, I couldn't create both `Ⅱ` and `ⅱ`.

, https://git.io/vM13d in Homebrew/homebrew-core
youtube-dl 2017.01.18
=====================

Created with `brew bump-formula-pr`.