Jiwon Seo's PEP 3102 implementation.
See SF#1549670.
The compiler package has not yet been updated.
diff --git a/Python/ceval.c b/Python/ceval.c
index dcbe53d..5d5acd0 100644
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -494,7 +494,7 @@
 			  (PyObject **)NULL, 0,
 			  (PyObject **)NULL, 0,
 			  (PyObject **)NULL, 0,
-			  NULL);
+			  NULL, NULL);
 }
 
 
@@ -2290,26 +2290,46 @@
 		}
 
 		case MAKE_FUNCTION:
+		{
+		    int posdefaults = oparg & 0xff;
+		    int kwdefaults = (oparg>>8) & 0xff;
+
 			v = POP(); /* code object */
 			x = PyFunction_New(v, f->f_globals);
 			Py_DECREF(v);
 			/* XXX Maybe this should be a separate opcode? */
-			if (x != NULL && oparg > 0) {
-				v = PyTuple_New(oparg);
+			if (x != NULL && posdefaults > 0) {
+				v = PyTuple_New(posdefaults);
 				if (v == NULL) {
 					Py_DECREF(x);
 					x = NULL;
 					break;
 				}
-				while (--oparg >= 0) {
+				while (--posdefaults >= 0) {
 					w = POP();
-					PyTuple_SET_ITEM(v, oparg, w);
+					PyTuple_SET_ITEM(v, posdefaults, w);
 				}
 				err = PyFunction_SetDefaults(x, v);
 				Py_DECREF(v);
 			}
+			if (x != NULL && kwdefaults > 0) {
+				v = PyDict_New();
+				if (v == NULL) {
+					Py_DECREF(x);
+					x = NULL;
+					break;
+				}
+				while (--kwdefaults >= 0) {
+					w = POP(); /* default value */
+					u = POP(); /* kw only arg name */
+					PyDict_SetItem(v, u, w);
+				}
+				err = PyFunction_SetKwDefaults(x, v);
+				Py_DECREF(v);
+			}
 			PUSH(x);
 			break;
+		}
 
 		case MAKE_CLOSURE:
 		{
@@ -2577,7 +2597,7 @@
 PyObject *
 PyEval_EvalCodeEx(PyCodeObject *co, PyObject *globals, PyObject *locals,
 	   PyObject **args, int argcount, PyObject **kws, int kwcount,
-	   PyObject **defs, int defcount, PyObject *closure)
+	   PyObject **defs, int defcount, PyObject *kwdefs, PyObject *closure)
 {
 	register PyFrameObject *f;
 	register PyObject *retval = NULL;
@@ -2601,6 +2621,7 @@
 	freevars = f->f_localsplus + co->co_nlocals;
 
 	if (co->co_argcount > 0 ||
+	    co->co_kwonlyargcount > 0 ||
 	    co->co_flags & (CO_VARARGS | CO_VARKEYWORDS)) {
 		int i;
 		int n = argcount;
@@ -2609,7 +2630,7 @@
 			kwdict = PyDict_New();
 			if (kwdict == NULL)
 				goto fail;
-			i = co->co_argcount;
+			i = co->co_argcount + co->co_kwonlyargcount;
 			if (co->co_flags & CO_VARARGS)
 				i++;
 			SETLOCAL(i, kwdict);
@@ -2618,7 +2639,7 @@
 			if (!(co->co_flags & CO_VARARGS)) {
 				PyErr_Format(PyExc_TypeError,
 				    "%.200s() takes %s %d "
-				    "%sargument%s (%d given)",
+				    "%spositional argument%s (%d given)",
 				    PyString_AsString(co->co_name),
 				    defcount ? "at most" : "exactly",
 				    co->co_argcount,
@@ -2638,7 +2659,7 @@
 			u = PyTuple_New(argcount - n);
 			if (u == NULL)
 				goto fail;
-			SETLOCAL(co->co_argcount, u);
+			SETLOCAL(co->co_argcount + co->co_kwonlyargcount, u);
 			for (i = n; i < argcount; i++) {
 				x = args[i];
 				Py_INCREF(x);
@@ -2656,7 +2677,9 @@
 				goto fail;
 			}
 			/* XXX slow -- speed up using dictionary? */
-			for (j = 0; j < co->co_argcount; j++) {
+			for (j = 0;
+			     j < co->co_argcount + co->co_kwonlyargcount;
+			     j++) {
 				PyObject *nm = PyTuple_GET_ITEM(
 					co->co_varnames, j);
 				int cmp = PyObject_RichCompareBool(
@@ -2669,7 +2692,7 @@
 			/* Check errors from Compare */
 			if (PyErr_Occurred())
 				goto fail;
-			if (j >= co->co_argcount) {
+			if (j >= co->co_argcount + co->co_kwonlyargcount) {
 				if (kwdict == NULL) {
 					PyErr_Format(PyExc_TypeError,
 					    "%.200s() got an unexpected "
@@ -2694,13 +2717,38 @@
 				SETLOCAL(j, value);
 			}
 		}
+		if (co->co_kwonlyargcount > 0) {
+			for (i = co->co_argcount;
+			     i < co->co_argcount + co->co_kwonlyargcount;
+			     i++) {
+				if (GETLOCAL(i) != NULL)
+					continue;
+				PyObject *name =
+				    PyTuple_GET_ITEM(co->co_varnames, i);
+				PyObject *def = NULL;
+				if (kwdefs != NULL)
+					def = PyDict_GetItem(kwdefs, name);
+				if (def != NULL) {
+					Py_INCREF(def);
+					SETLOCAL(i, def);
+					continue;
+				}
+				PyErr_Format(PyExc_TypeError,
+					"%.200s() needs "
+					"keyword only argument %s",
+					PyString_AsString(co->co_name),
+					PyString_AsString(name));
+				goto fail;
+			}
+		}
 		if (argcount < co->co_argcount) {
 			int m = co->co_argcount - defcount;
 			for (i = argcount; i < m; i++) {
 				if (GETLOCAL(i) == NULL) {
 					PyErr_Format(PyExc_TypeError,
 					    "%.200s() takes %s %d "
-					    "%sargument%s (%d given)",
+					    "%spositional argument%s "
+					    "(%d given)",
 					    PyString_AsString(co->co_name),
 					    ((co->co_flags & CO_VARARGS) ||
 					     defcount) ? "at least"
@@ -3565,12 +3613,14 @@
 	PyCodeObject *co = (PyCodeObject *)PyFunction_GET_CODE(func);
 	PyObject *globals = PyFunction_GET_GLOBALS(func);
 	PyObject *argdefs = PyFunction_GET_DEFAULTS(func);
+	PyObject *kwdefs = PyFunction_GET_KW_DEFAULTS(func);
 	PyObject **d = NULL;
 	int nd = 0;
 
 	PCALL(PCALL_FUNCTION);
 	PCALL(PCALL_FAST_FUNCTION);
-	if (argdefs == NULL && co->co_argcount == n && nk==0 &&
+	if (argdefs == NULL && co->co_argcount == n &&
+	    co->co_kwonlyargcount == 0 && nk==0 &&
 	    co->co_flags == (CO_OPTIMIZED | CO_NEWLOCALS | CO_NOFREE)) {
 		PyFrameObject *f;
 		PyObject *retval = NULL;
@@ -3608,7 +3658,7 @@
 	}
 	return PyEval_EvalCodeEx(co, globals,
 				 (PyObject *)NULL, (*pp_stack)-n, na,
-				 (*pp_stack)-2*nk, nk, d, nd,
+				 (*pp_stack)-2*nk, nk, d, nd, kwdefs,
 				 PyFunction_GET_CLOSURE(func));
 }