Compare commits

...
10 Commits
35 changed files with 12373 additions and 58678 deletions

No files matched your search

+1
View File
@@ -11,6 +11,7 @@ notes for it.
.. toctree::
:maxdepth: 1
release_notes_4_5
release_notes_4_4
release_notes_4_3
release_notes_4_2
+17
View File
@@ -0,0 +1,17 @@
***********
Version 4.5
***********
Release date: 2019-04-10
This release contains a number of new features and fixes reported since the
release of pgAdmin4 4.4.
Bug fixes
*********
| `Bug #2214 <https://redmine.postgresql.org/issues/2214>`_ - Fixed 'Change Password' issue for SCRAM authentication.
| `Bug #3656 <https://redmine.postgresql.org/issues/3656>`_ - Ensure that two consecutive SELECT statements should work properly.
| `Bug #4131 <https://redmine.postgresql.org/issues/4131>`_ - Relabel the Save button on the datagrid text editor to avoid confusion with the actual Save button that updates the database.
| `Bug #4142 <https://redmine.postgresql.org/issues/4142>`_ - Added recommended ESLinter checks.
| `Bug #4143 <https://redmine.postgresql.org/issues/4143>`_ - Ensure that pgAdmin4 should work properly with psycopg2 v2.8
+1 -1
View File
@@ -21,7 +21,7 @@ sqlparse==0.2.4
WTForms==2.2.1
Flask-Paranoid==0.2.0
psutil==5.5.1
psycopg2>=2.7.7
psycopg2>=2.8
python-dateutil>=2.8.0
htmlmin==0.1.12
Flask-HTMLmin==1.5.0
+2 -2
View File
@@ -8,9 +8,9 @@
<key>CFBundleName</key>
<string>pgAdmin 4</string>
<key>CFBundleShortVersionString</key>
<string>4.4.0</string>
<string>4.5.0</string>
<key>CFBundleVersion</key>
<string>4.4.0</string>
<string>4.5.0</string>
<key>LSMinimumSystemVersion</key>
<string>10.10</string>
<key>NSHumanReadableCopyright</key>
+1 -1
View File
@@ -1,4 +1,4 @@
VERSION = 4.4.0.0
VERSION = 4.5.0.0
QMAKE_TARGET_COMPANY = "The pgAdmin Development Team"
QMAKE_TARGET_PRODUCT = "pgAdmin 4"
QMAKE_TARGET_DESCRIPTION = "pgAdmin 4 Desktop Runtime"
+5
View File
@@ -14,6 +14,9 @@ module.exports = {
'amd': true,
'jasmine': true,
},
'extends': [
'eslint:recommended',
],
'parserOptions': {
'ecmaVersion': 2018,
'sourceType': 'module',
@@ -43,5 +46,7 @@ module.exports = {
'always-multiline'
],
'no-console': ["error", { allow: ["warn", "error"] }],
// We need to exclude below for RegEx case
"no-useless-escape": 0,
},
};
+2 -2
View File
@@ -50,7 +50,7 @@ APP_ICON = 'pg-icon'
# Application version number components
APP_RELEASE = 4
APP_REVISION = 4
APP_REVISION = 5
# Application version suffix, e.g. 'beta1', 'dev'. Usually an empty string
# for GA releases.
@@ -59,7 +59,7 @@ APP_SUFFIX = ''
# Numeric application version for upgrade checks. Should be in the format:
# [X]XYYZZ, where X is the release version, Y is the revision, with a leading
# zero if needed, and Z represents the suffix, with a leading zero if needed
APP_VERSION_INT = 40400
APP_VERSION_INT = 40500
# DO NOT CHANGE!
# The application version string, constructed from the components
@@ -240,7 +240,6 @@ define('pgadmin.node.column', [
return false;
},
editable: function(m) {
var name = m.get('name');
// If HeaderCell then allow True
if(m instanceof Backbone.Collection) {
return true;
-1
View File
@@ -1070,7 +1070,6 @@ define('pgadmin.browser', [
var loaded = this.t.wasLoad(parent),
onLoad = function() {
self.i = parent;
self.d = self.d;
self.pathOfTreeItems.push({coll: false, item: parent, d: self.d});
self.success();
return;
@@ -6,6 +6,7 @@
# This software is released under the PostgreSQL Licence
#
##########################################################################
import random
from regression.python_test_utils import test_utils
from regression.feature_utils.base_feature_test import BaseFeatureTest
@@ -19,35 +20,40 @@ class CheckRoleMembershipControlFeatureTest(BaseFeatureTest):
dict())
]
role = ""
def before(self):
with test_utils.Database(self.server) as (connection, _):
if connection.server_version < 90100:
self.skipTest(
"Membership is not present in Postgres below PG v9.1")
# create role
self.role = "test_role" + str(random.randint(10000, 65535))
# Some test function is needed for debugger
test_utils.create_role(self.server, "postgres",
"test_role")
self.role)
test_utils.create_role(self.server, "postgres",
"<h1>test</h1>")
def runTest(self):
self.page.wait_for_spinner_to_disappear()
self.page.add_server(self.server)
self._role_node_expandable()
self._role_node_expandable(self.role)
self._check_role_membership_control()
def after(self):
self.page.remove_server(self.server)
test_utils.drop_role(self.server, "postgres",
"test_role")
self.role)
test_utils.drop_role(self.server, "postgres",
"<h1>test</h1>")
def _role_node_expandable(self):
def _role_node_expandable(self, role):
self.page.toggle_open_server(self.server['name'])
self.page.toggle_open_tree_item('Login/Group Roles')
self.page.select_tree_item("test_role")
self.page.select_tree_item(role)
def _check_role_membership_control(self):
self.page.driver.find_element_by_link_text("Object").click()
+1 -1
View File
@@ -24,4 +24,4 @@ export function getHelpUrl(base_path, file, version) {
}
return url + file;
};
}
+1317 -6473
View File
File diff suppressed because it is too large. Load diff
+6 -1
View File
@@ -38,7 +38,12 @@ define([], function() {
var o, n, i, l, d, c = /^top|bottom/,
f = ['paddingTop', 'paddingBottom', 'borderTop', 'borderBottom'],
u = 4;
if (o = m ? m(t)[e] : (n = t.style['pixel' + e.charAt(0).toUpperCase() + e.slice(1)]) ? n + 'px' : 'fontSize' === e ? r(t, '1em', 'left', 1) + 'px' : t.currentStyle[e], i = (o.match(s) || [])[2], '%' === i && p)
n = t.style['pixel' + e.charAt(0).toUpperCase() + e.slice(1)];
o = m ? m(t)[e] : (n) ? n + 'px' : 'fontSize' === e ? r(t, '1em', 'left', 1) + 'px' : t.currentStyle[e];
i = (o.match(s) || [])[2];
if ('%' === i && p)
if (c.test(e)) {
for (l = (d = t.parentNode || t).offsetHeight; u--;) l -= parseFloat(a(d, f[u]));
o = parseFloat(o) / 100 * l + 'px';
+11 -10
View File
@@ -14,6 +14,7 @@
*/
import JSONBigNumber from 'json-bignumber';
import gettext from 'sources/gettext';
(function($, JSONBigNumber) {
// register namespace
@@ -46,7 +47,7 @@ import JSONBigNumber from 'json-bignumber';
// Generate and return editor buttons
function getButtons(editable) {
var $buttons = $('<div class=\'pg_buttons\' />'),
label = editable ? 'Cancel' : 'OK',
label = editable ? gettext('Cancel') : gettext('OK'),
button_type = editable ? 'btn-secondary' : 'btn-primary',
button_icon = editable ? 'fa-times' : 'fa-check';
@@ -56,8 +57,8 @@ import JSONBigNumber from 'json-bignumber';
.appendTo($buttons);
if (editable) {
$('<button class=\'btn btn-primary long_text_editor\' data-label="Save">'+
'<span class="fa fa-save pg-alertify-button"></span>&nbsp;Save'+
$('<button class=\'btn btn-primary long_text_editor\' data-label="' + gettext('OK') + '">'+
'<span class="fa fa-check pg-alertify-button"></span>&nbsp;' + gettext('OK') +
'</button>')
.appendTo($buttons);
}
@@ -276,7 +277,7 @@ import JSONBigNumber from 'json-bignumber';
if (args.column.is_array && !is_valid_array($input.val())) {
return {
valid: false,
msg: 'Array must start with \'{\' and end with \'}\'',
msg: gettext('Arrays must start with "{" and end with "}"'),
};
}
@@ -640,7 +641,7 @@ import JSONBigNumber from 'json-bignumber';
var defaultValue;
this.init = function() {
$input = $('<INPUT type=text class=\'editor-text\' readonly/>')
$input = $('<input type=text class=\'editor-text\' readonly/>')
.appendTo(args.container)
.on('keydown.nav', function(e) {
if (e.keyCode === $.ui.keyCode.LEFT || e.keyCode === $.ui.keyCode.RIGHT) {
@@ -710,7 +711,7 @@ import JSONBigNumber from 'json-bignumber';
var defaultValue;
this.init = function() {
$select = $('<INPUT type=checkbox value=\'true\' class=\'editor-checkbox\' hideFocus disabled>');
$select = $('<input type=checkbox value=\'true\' class=\'editor-checkbox\' hideFocus disabled>');
$select.appendTo(args.container);
$select.trigger('focus');
};
@@ -773,7 +774,7 @@ import JSONBigNumber from 'json-bignumber';
var defaultValue;
this.init = function() {
$input = $('<INPUT type=text class=\'editor-text\' />');
$input = $('<input type=text class=\'editor-text\' />');
$input.on('keydown.nav', function(e) {
if (e.keyCode === $.ui.keyCode.LEFT || e.keyCode === $.ui.keyCode.RIGHT) {
@@ -836,7 +837,7 @@ import JSONBigNumber from 'json-bignumber';
if (!args.column.is_array && isNaN(value)) {
return {
valid: false,
msg: 'Please enter a valid number',
msg: gettext('Please enter a valid number'),
};
}
if (args.column.validator) {
@@ -850,7 +851,7 @@ import JSONBigNumber from 'json-bignumber';
if (!is_valid_array(value)) {
return {
valid: false,
msg: 'Array must start with \'{\' and end with \'}\'',
msg: gettext('Arrays must start with "{" and end with "}"'),
};
}
@@ -867,7 +868,7 @@ import JSONBigNumber from 'json-bignumber';
if (isNaN(arr[k])) {
return {
valid: false,
msg: 'Please enter a valid numbers',
msg: gettext('Please enter a valid number'),
};
}
}
@@ -8,6 +8,8 @@
##########################################################################
import sys
import random
from pgadmin.utils.route import BaseTestGenerator
from regression.python_test_utils import test_utils
from pgadmin.utils import server_utils
@@ -56,7 +58,8 @@ class TestSQLASCIIEncoding(BaseTestGenerator):
]
def setUp(self):
self.encode_db_name = 'test_encoding_' + self.db_encoding
self.encode_db_name = 'test_encoding_' + self.db_encoding + \
str(random.randint(1000, 65535))
self.encode_sid = self.server_information['server_id']
server_con = server_utils.connect_server(self, self.encode_sid)
Binary file not shown.
File diff suppressed because it is too large. Load diff
Binary file not shown.
File diff suppressed because it is too large. Load diff
Binary file not shown.
File diff suppressed because it is too large. Load diff
Binary file not shown.
File diff suppressed because it is too large. Load diff
Binary file not shown.
File diff suppressed because it is too large. Load diff
Binary file not shown.
File diff suppressed because it is too large. Load diff
Binary file not shown.
File diff suppressed because it is too large. Load diff
Binary file not shown.
File diff suppressed because it is too large. Load diff
+21 -1
View File
@@ -18,6 +18,8 @@ try:
except ImportError:
from ordereddict import OrderedDict
import psycopg2
from psycopg2.extensions import cursor as _cursor, encodings
from .encoding import configureDriverEncodings
@@ -91,7 +93,25 @@ class _WrapperColumn(object):
Generates an OrderedDict from the fields of the original objects
with avoiding the duplicate name.
"""
ores = OrderedDict(self.orig_col._asdict())
# In psycopg2 2.8, the description of one result column,
# exposed as items of the cursor.description sequence.
# Before psycopg2 2.8 the description attribute was a sequence
# of simple tuples or namedtuples.
if psycopg2.__version__.find('2.8') != -1:
ores = OrderedDict()
ores['name'] = self.orig_col.name
ores['type_code'] = self.orig_col.type_code
ores['display_size'] = self.orig_col.display_size
ores['internal_size'] = self.orig_col.internal_size
ores['precision'] = self.orig_col.precision
ores['scale'] = self.orig_col.scale
ores['null_ok'] = self.orig_col.null_ok
ores['table_oid'] = self.orig_col.table_oid
ores['table_column'] = self.orig_col.table_column
else:
ores = OrderedDict(self.orig_col._asdict())
name = ores['name']
if self.dummy_name:
ores['name'] = self.dummy_name
+2 -2
View File
@@ -182,7 +182,7 @@ class PgadminPage:
ActionChains(self.driver).double_click(item).perform()
def toggle_open_tables_node(self):
"""The function will be used for opening Trees node only"""
"""The function will be used for opening Tables node only"""
# get the element which contains 'aria-expanded' info
tables_expansion_ele = self.find_by_xpath("//div[div[div[div[div[div"
@@ -479,7 +479,7 @@ class PgadminPage:
return element_selector(self.driver)
def _wait_for(self, waiting_for_message, condition_met_function,
timeout=None):
timeout=3):
if timeout is None:
timeout = self.timeout
return WebDriverWait(self.driver, timeout, 0.01).until(
@@ -26,8 +26,19 @@ def close_bgprocess_popup(tester):
# In cases where restore div is not closed (sometime due to some error)
try:
if tester.driver.find_element_by_xpath(
"//div[@class='card-header bg-primary d-flex']/div[contains("
"text(), 'Restoring backup')]"):
"//div[@class='card-header bg-primary d-flex']/div"
"[contains(text(), 'Restoring backup')]"):
tester.driver.find_element_by_css_selector(
".btn.btn-sm-sq.btn-primary.pg-bg-close > i").click()
except Exception:
pass
# In cases where maintenance window is not closed (sometime due to some
# error)
try:
if tester.driver.find_element_by_xpath(
"//div[@class='card-header bg-primary d-flex']/div"
"[contains(text(), 'Maintenance')]"):
tester.driver.find_element_by_css_selector(
".btn.btn-sm-sq.btn-primary.pg-bg-close > i").click()
except Exception:
+3
View File
@@ -219,6 +219,9 @@ def get_test_modules(arguments):
options.add_argument("--window-size=1280,1024")
driver = webdriver.Chrome(chrome_options=options)
# maximize browser window
driver.maximize_window()
app_starter = AppStarter(driver, config)
app_starter.start_app()