Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
S
settingsd
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
1
Merge Requests
1
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
etersoft
settingsd
Commits
de464448
Commit
de464448
authored
Jan 23, 2019
by
Дмитрий Никулин
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Switch to Python 3; drop Python 2 compatibility
parent
87d14422
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
81 additions
and
106 deletions
+81
-106
settingsd-server.py
settingsd-server.py
+16
-16
application.py
settingsd/application.py
+6
-6
config.py
settingsd/config.py
+7
-8
daemon.py
settingsd/daemon.py
+5
-5
logger.py
settingsd/logger.py
+3
-3
server.py
settingsd/server.py
+7
-7
service.py
settingsd/service.py
+9
-19
service_decorators.py
settingsd/service_decorators.py
+8
-7
shared.py
settingsd/shared.py
+11
-26
editors.py
settingsd/tools/editors.py
+2
-2
__init__.py
settingsd/validators/__init__.py
+1
-1
network.py
settingsd/validators/network.py
+5
-5
os.py
settingsd/validators/os.py
+1
-1
No files found.
settingsd-server.py
View file @
de464448
...
...
@@ -14,7 +14,7 @@ from settingsd import daemon
##### Private methods #####
def
help
()
:
print
(
"Usage:
%
s [options]
\n
"
print
(
(
"Usage:
%
s [options]
\n
"
"Options:
\n
"
"
\t
-h, --help -- Print this text
\n
"
"
\t
-v, --version -- Print version and license info
\n
"
...
...
@@ -23,10 +23,10 @@ def help() :
"
\t
--bus-type=<system|session> -- Use system or session bus, replace value from config
\n
"
"
\t
-d, --daemon -- Run application as daemon, by default using interactive mode
\n
"
"
\t
-s, --status -- Check status of daemon
\n
"
"
\t
-k, --kill -- Kill daemon process"
%
(
const
.
MY_NAME
)
)
"
\t
-k, --kill -- Kill daemon process"
%
(
const
.
MY_NAME
)
)
)
def
version
()
:
print
"
%
s version
%
s-
%
s, functionality_level=
%
d"
%
(
const
.
MY_NAME
,
const
.
VERSION
,
const
.
VERSION_STATUS
,
const
.
FUNCTIONALITY_LEVEL
)
print
(
"
%
s version
%
s-
%
s, functionality_level=
%
d"
%
(
const
.
MY_NAME
,
const
.
VERSION
,
const
.
VERSION_STATUS
,
const
.
FUNCTIONALITY_LEVEL
)
)
##### Main #####
...
...
@@ -52,22 +52,22 @@ if __name__ == "__main__" :
elif
opts_list_item
in
(
"--log-level"
,)
:
try
:
log_level
=
validators
.
common
.
validRange
(
int
(
args_list_item
),
const
.
ALL_LOG_LEVELS_LIST
)
except
Exception
,
err1
:
print
"Incorrect option
\"
%
s
\"
:
%
s"
%
(
opts_list_item
,
str
(
err1
))
except
Exception
as
err1
:
print
(
"Incorrect option
\"
%
s
\"
:
%
s"
%
(
opts_list_item
,
str
(
err1
)
))
sys
.
exit
(
1
)
elif
opts_list_item
in
(
"--use-syslog"
,)
:
try
:
use_syslog_flag
=
validators
.
common
.
validBool
(
args_list_item
)
except
Exception
,
err1
:
print
"Incorrect option
\"
%
s
\"
:
%
s"
%
(
opts_list_item
,
str
(
err1
))
except
Exception
as
err1
:
print
(
"Incorrect option
\"
%
s
\"
:
%
s"
%
(
opts_list_item
,
str
(
err1
)
))
sys
.
exit
(
1
)
elif
opts_list_item
in
(
"--bus-type"
,)
:
try
:
bus_type
=
validators
.
common
.
validRange
(
args_list_item
,
const
.
ALL_BUS_TYPES_LIST
)
except
Exception
,
err1
:
print
"Incorrect option
\"
%
s
\"
:
%
s"
%
(
opts_list_item
,
str
(
err1
))
except
Exception
as
err1
:
print
(
"Incorrect option
\"
%
s
\"
:
%
s"
%
(
opts_list_item
,
str
(
err1
)
))
sys
.
exit
(
1
)
elif
opts_list_item
in
(
"-d"
,
"--daemon"
)
:
...
...
@@ -76,21 +76,21 @@ if __name__ == "__main__" :
elif
opts_list_item
in
(
"-s"
,
"--status"
)
:
try
:
sys
.
exit
(
abs
(
daemon
.
daemonStatus
()))
except
Exception
,
err1
:
print
"Daemon status error:
%
s"
%
(
str
(
err1
))
except
Exception
as
err1
:
print
(
"Daemon status error:
%
s"
%
(
str
(
err1
)
))
sys
.
exit
(
1
)
elif
opts_list_item
in
(
"-k"
,
"--kill"
)
:
try
:
sys
.
exit
(
abs
(
daemon
.
killDaemon
()))
except
Exception
,
err1
:
print
"Daemon kill error:
%
s"
%
(
str
(
err1
))
except
Exception
as
err1
:
print
(
"Daemon kill error:
%
s"
%
(
str
(
err1
)
))
sys
.
exit
(
1
)
else
:
print
"Unknown option
\"
%
s
\"
"
%
(
opts_list_item
)
except
Exception
,
err1
:
print
"Bad command line options:
%
s"
%
(
str
(
err1
))
print
(
"Unknown option
\"
%
s
\"
"
%
(
opts_list_item
)
)
except
Exception
as
err1
:
print
(
"Bad command line options:
%
s"
%
(
str
(
err1
)
))
#####
...
...
settingsd/application.py
View file @
de464448
...
...
@@ -6,11 +6,11 @@ import os
import
signal
import
syslog
import
const
import
config
import
logger
import
server
import
daemon
from
.
import
const
from
.
import
config
from
.
import
logger
from
.
import
server
from
.
import
daemon
##### Public classes #####
...
...
@@ -122,7 +122,7 @@ class Application(object) :
def
runDaemon
(
self
)
:
work_dir_path
=
(
"/"
if
os
.
getuid
()
==
0
else
None
)
umask
=
(
077
if
os
.
getuid
()
==
0
else
None
)
umask
=
(
0
o
77
if
os
.
getuid
()
==
0
else
None
)
logger
.
info
(
"Run server as daemon: uid=
%
d, dir=
%
s, umask=
%
s"
%
(
os
.
getuid
(),
(
work_dir_path
if
work_dir_path
!=
None
else
os
.
getcwd
()
),
...
...
settingsd/config.py
View file @
de464448
...
...
@@ -2,11 +2,10 @@
import
os
import
ConfigP
arser
import
configp
arser
import
const
import
validators
import
validators.common
from
.
import
const
from
.
import
validators
##### Public constants #####
...
...
@@ -40,16 +39,16 @@ ConfigDictObject = {
def
setValue
(
section
,
option
,
value
,
validator
=
None
)
:
global
ConfigDictObject
if
not
ConfigDictObject
.
has_key
(
section
)
:
if
section
not
in
ConfigDictObject
:
ConfigDictObject
[
section
]
=
{}
if
ConfigDictObject
[
section
]
.
has_key
(
option
)
:
if
option
in
ConfigDictObject
[
section
]
:
validator
=
ConfigDictObject
[
section
][
option
][
1
]
if
validator
!=
None
:
try
:
value
=
validator
(
value
)
except
Exception
,
err1
:
except
Exception
as
err1
:
raise
validators
.
ValidatorError
(
"Incorrect config option
\"
%
s ::
%
s =
%
s
\"
:
%
s"
%
(
section
,
option
,
value
,
str
(
err1
)))
ConfigDictObject
[
section
][
option
]
=
(
value
,
validator
)
...
...
@@ -69,7 +68,7 @@ def loadConfigs(only_sections_list = (), exclude_sections_list = ()) :
if
not
config_files_list_item
.
endswith
(
const
.
CONFIG_FILE_POSTFIX
)
:
continue
config_parser
=
ConfigP
arser
.
ConfigParser
()
config_parser
=
configp
arser
.
ConfigParser
()
config_parser
.
read
(
os
.
path
.
join
(
const
.
CONFIGS_DIR
,
config_files_list_item
))
for
section
in
config_parser
.
sections
()
:
...
...
settingsd/daemon.py
View file @
de464448
...
...
@@ -7,8 +7,8 @@ import signal
import
errno
import
resource
import
const
import
logger
from
.
import
const
from
.
import
logger
##### Private methods #####
...
...
@@ -58,10 +58,10 @@ def maxFd() :
return
max_fd
def
closeFd
(
fd
,
retries_count
=
5
)
:
for
count
in
x
range
(
retries_count
)
:
for
count
in
range
(
retries_count
)
:
try
:
os
.
close
(
fd
)
except
OSError
,
err1
:
except
OSError
as
err1
:
if
err1
.
errno
!=
errno
.
EBADF
:
continue
break
...
...
@@ -92,7 +92,7 @@ def startDaemon(function, work_dir_path = None, umask = None) :
os
.
umask
(
umask
)
logger
.
verbose
(
"Accapted new umask:
%.3
o"
%
(
umask
))
for
fd
in
x
range
(
maxFd
())
:
for
fd
in
range
(
maxFd
())
:
closeFd
(
fd
)
null_fd
=
os
.
open
(
"/dev/null"
,
os
.
O_RDWR
)
for
fd
in
(
0
,
1
,
2
)
:
...
...
settingsd/logger.py
View file @
de464448
...
...
@@ -7,8 +7,8 @@ import syslog
import
inspect
import
time
import
const
import
config
from
.
import
const
from
.
import
config
##### Public constants #####
...
...
@@ -77,7 +77,7 @@ def log(message_type, message) :
colored_index
=
int
(
sys
.
stderr
.
isatty
()
and
config
.
value
(
config
.
APPLICATION_SECTION
,
"log_use_colors"
))
for
message_list_item
in
message
.
split
(
"
\n
"
)
:
print
>>
sys
.
stderr
,
"[
%
s ]
%
s"
%
(
ALL_MESSAGES_TEXTS_LIST
[
message_type
[
0
]][
colored_index
],
message_list_item
)
print
(
"[
%
s ]
%
s"
%
(
ALL_MESSAGES_TEXTS_LIST
[
message_type
[
0
]][
colored_index
],
message_list_item
),
file
=
sys
.
stderr
)
if
config
.
value
(
config
.
RUNTIME_SECTION
,
"use_syslog"
)
:
syslog
.
syslog
(
message_type
[
1
],
"[
%
s ]
%
s"
%
(
ALL_MESSAGES_TEXTS_LIST
[
message_type
[
0
]][
0
],
message_list_item
))
...
...
settingsd/server.py
View file @
de464448
...
...
@@ -8,10 +8,10 @@ import dbus.service
import
dbus.glib
import
gobject
import
const
import
config
import
logger
import
validators.common
from
.
import
const
from
.
import
config
from
.
import
logger
from
.
import
validators
##### Public classes #####
...
...
@@ -70,7 +70,7 @@ class Server(object) :
config
.
loadConfigs
(
only_sections_list
=
(
config
.
APPLICATION_SECTION
,))
def
loadServicesConfigs
(
self
)
:
for
service_name
in
self
.
__services_dict
.
keys
(
)
:
for
service_name
in
list
(
self
.
__services_dict
.
keys
()
)
:
service_options_list
=
list
(
self
.
__services_dict
[
service_name
][
"service_class"
]
.
options
())
service_options_list
.
append
((
service_name
,
"enabled"
,
"no"
,
validators
.
common
.
validBool
))
...
...
@@ -102,7 +102,7 @@ class Server(object) :
###
def
initServices
(
self
)
:
for
service_name
in
self
.
__services_dict
.
keys
(
)
:
for
service_name
in
list
(
self
.
__services_dict
.
keys
()
)
:
if
config
.
value
(
service_name
,
"enabled"
)
:
logger
.
verbose
(
"Enabling service
\"
%
s
\"
..."
%
(
service_name
))
try
:
...
...
@@ -114,7 +114,7 @@ class Server(object) :
logger
.
info
(
"Initialized service:
%
s"
%
(
service_name
))
def
closeServices
(
self
)
:
for
service_name
in
self
.
__services_dict
.
keys
(
)
:
for
service_name
in
list
(
self
.
__services_dict
.
keys
()
)
:
if
self
.
__services_dict
[
service_name
][
"service"
]
!=
None
:
logger
.
verbose
(
"Disabling service
\"
%
s
\"
..."
%
(
service_name
))
try
:
...
...
settingsd/service.py
View file @
de464448
...
...
@@ -6,22 +6,17 @@ import dbus.service
import
dbus.glib
import
abc
import
const
import
config
import
shared
import
logger
import
tools.dbu
s
from
.
import
const
from
.
import
config
from
.
import
shared
from
.
import
logger
from
.
import
tool
s
from
service_decorators
import
*
from
.
service_decorators
import
*
##### Private classes #####
class
ServiceInterface
(
object
)
:
__metaclass__
=
abc
.
ABCMeta
### Public ###
class
ServiceInterface
(
object
,
metaclass
=
abc
.
ABCMeta
)
:
@abc.abstractmethod
def
initService
(
self
)
:
pass
...
...
@@ -29,12 +24,7 @@ class ServiceInterface(object) :
def
closeService
(
self
)
:
pass
class
ServiceRequisitesInterface
(
object
)
:
__metaclass__
=
abc
.
ABCMeta
### Public ###
class
ServiceRequisitesInterface
(
object
,
metaclass
=
abc
.
ABCMeta
)
:
@classmethod
@abc.abstractmethod
def
serviceName
(
self
)
:
...
...
@@ -68,7 +58,7 @@ class CustomObject(dbus.service.Object) :
def
name
(
self
)
:
if
self
.
shared
()
==
None
:
return
None
for
(
shared_object_name
,
shared_object
)
in
self
.
shared
()
.
sharedObjects
()
.
items
(
)
:
for
(
shared_object_name
,
shared_object
)
in
list
(
self
.
shared
()
.
sharedObjects
()
.
items
()
)
:
if
shared_object
==
self
:
return
shared_object_name
return
None
...
...
settingsd/service_decorators.py
View file @
de464448
...
...
@@ -5,10 +5,11 @@ import dbus
import
dbus.service
import
dbus.glib
import
const
import
config
import
logger
import
tools.dbus
from
.
import
const
from
.
import
config
from
.
import
logger
from
.
import
tools
from
.tools
import
dbus
as
dbus_tools
##### Private decorators #####
...
...
@@ -16,9 +17,9 @@ def tracer(function, statics_list=[0]) :
def
wrapper
(
self
,
*
args_list
,
**
kwargs_dict
)
:
if
config
.
value
(
config
.
APPLICATION_SECTION
,
"log_level"
)
==
const
.
LOG_LEVEL_DEBUG
:
logger
.
debug
(
"
%
s
%
s
%
s::
%
s"
%
(
" "
*
statics_list
[
0
],
str
((
function
.
__dict__
.
has_key
(
"_dbus_is_method"
)
and
"Called method"
)
or
(
function
.
__dict__
.
has_key
(
"_dbus_is_signal"
)
and
"Emited signal"
)),
self
.
objectPath
(),
tools
.
dbu
s
.
joinMethod
(
function
.
_dbus_interface
,
function
.
__name__
)
))
str
((
"_dbus_is_method"
in
function
.
__dict__
and
"Called method"
)
or
(
"_dbus_is_signal"
in
function
.
__dict__
and
"Emited signal"
)),
self
.
objectPath
(),
dbus_tool
s
.
joinMethod
(
function
.
_dbus_interface
,
function
.
__name__
)
))
statics_list
[
0
]
+=
1
try
:
...
...
settingsd/shared.py
View file @
de464448
...
...
@@ -39,7 +39,7 @@ class SharedAbstract :
def
name
(
entity
)
:
if
entity
.
parentShared
()
==
None
:
return
None
for
(
shared_name
,
shared
)
in
entity
.
parentShared
()
.
shareds
()
.
items
(
)
:
for
(
shared_name
,
shared
)
in
list
(
entity
.
parentShared
()
.
shareds
()
.
items
()
)
:
if
shared
==
entity
:
return
shared_name
return
None
...
...
@@ -47,7 +47,7 @@ class SharedAbstract :
###
def
addShared
(
entity
,
shared_name
)
:
if
entity
.
_shareds_dict
.
has_key
(
shared_name
)
:
if
shared_name
in
entity
.
_shareds_dict
:
raise
SharedsConflict
(
"Shared
\"
%
s
\"
is already exists in collection
\"
%
s
\"
"
%
(
shared_name
,
entity
.
__name__
))
entity
.
_shareds_dict
[
shared_name
]
=
Shared
()
...
...
@@ -55,7 +55,7 @@ class SharedAbstract :
setattr
(
entity
,
shared_name
,
entity
.
_shareds_dict
[
shared_name
])
def
removeShared
(
entity
,
shared_name
)
:
if
not
entity
.
_shareds_dict
.
has_key
(
shared_name
)
:
if
shared_name
not
in
entity
.
_shareds_dict
:
raise
SharedNotExists
(
"Shared
\"
%
s
\"
does not exist in collection
\"
%
s
\"
"
%
(
shared_name
,
entity
.
__name__
))
entity
.
_shareds_dict
[
shared_name
]
.
setParentShared
(
None
)
...
...
@@ -63,7 +63,7 @@ class SharedAbstract :
delattr
(
entity
,
shared_name
)
def
hasShared
(
entity
,
shared_name
)
:
return
entity
.
_shareds_dict
.
has_key
(
shared_name
)
return
shared_name
in
entity
.
_shareds_dict
def
shared
(
entity
,
shared_name
)
:
return
entity
.
_shareds_dict
[
shared_name
]
...
...
@@ -74,7 +74,7 @@ class SharedAbstract :
###
def
addSharedObject
(
entity
,
shared_object_name
,
shared_object
)
:
if
entity
.
_shared_objects_dict
.
has_key
(
shared_object_name
)
:
if
shared_object_name
in
entity
.
_shared_objects_dict
:
raise
SharedObjectsConflict
(
"Shared object
\"
%
s
\"
is already exists in collection
\"
%
s
\"
"
%
(
shared_object_name
,
entity
.
__name__
))
entity
.
_shared_objects_dict
[
shared_object_name
]
=
shared_object
...
...
@@ -82,7 +82,7 @@ class SharedAbstract :
setattr
(
entity
,
shared_object_name
,
entity
.
_shared_objects_dict
[
shared_object_name
])
def
removeSharedObject
(
entity
,
shared_object_name
)
:
if
not
entity
.
_shared_objects_dict
.
has_key
(
shared_object_name
)
:
if
shared_object_name
not
in
entity
.
_shared_objects_dict
:
raise
SharedObjectNotExists
(
"Shared object
\"
%
s
\"
does not exist in collection
\"
%
s
\"
"
%
(
shared_object_name
,
entity
.
__name__
))
entity
.
_shared_objects_dict
[
shared_object_name
]
.
setShared
(
None
)
...
...
@@ -90,7 +90,7 @@ class SharedAbstract :
delattr
(
entity
,
shared_object_name
)
def
hasSharedObject
(
entity
,
shared_object
)
:
return
(
entity
.
_shared_objects_dict
.
has_key
(
shared_object
)
or
shared_object
in
entity
.
_shared_objects_dict
.
values
(
)
)
return
(
shared_object
in
entity
.
_shared_objects_dict
or
shared_object
in
list
(
entity
.
_shared_objects_dict
.
values
()
)
)
def
sharedObject
(
entity
,
shared_object_name
)
:
return
entity
.
_shared_objects_dict
[
shared_object_name
]
...
...
@@ -103,39 +103,24 @@ class SharedRootMeta(type, SharedAbstract) :
type
.
__init__
(
cls
,
name
,
bases_list
,
attrs_dict
)
SharedAbstract
.
__init__
(
cls
)
class
Shared
(
object
,
SharedAbstract
)
:
class
Shared
(
SharedAbstract
)
:
def
__init__
(
self
)
:
object
.
__init__
(
self
)
SharedAbstract
.
__init__
(
self
)
##### Public classes #####
class
Functions
(
object
)
:
__metaclass__
=
SharedRootMeta
### Public ###
class
Functions
(
object
,
metaclass
=
SharedRootMeta
)
:
@classmethod
def
name
(
self
)
:
return
"Functions"
class
Actions
(
object
)
:
__metaclass__
=
SharedRootMeta
### Public ###
class
Actions
(
object
,
metaclass
=
SharedRootMeta
)
:
@classmethod
def
name
(
self
)
:
return
"Actions"
class
Customs
(
object
)
:
__metaclass__
=
SharedRootMeta
### Public ###
class
Customs
(
object
,
metaclass
=
SharedRootMeta
)
:
@classmethod
def
name
(
self
)
:
return
"Customs"
...
...
settingsd/tools/editors.py
View file @
de464448
...
...
@@ -115,7 +115,7 @@ class PlainEditor(object) :
space
=
(
" "
if
len
(
self
.
__spaces_list
)
>
0
else
""
)
quote
=
(
self
.
__quotes_list
[
0
]
if
len
(
self
.
__quotes_list
)
>
0
else
""
)
for
count
in
x
range
(
len
(
values_list
))
:
for
count
in
range
(
len
(
values_list
))
:
variable
=
variable_name
+
space
+
self
.
__delimiter
+
space
+
quote
+
str
(
values_list
[
count
])
+
quote
self
.
__config_file_data_list
.
insert
(
last_variable_index
+
count
,
variable
)
...
...
@@ -243,7 +243,7 @@ class IniEditor(object) :
self
.
__config_file_data_list
.
insert
(
last_variable_index
+
1
,
"[
%
s]"
%
(
section_name
))
last_variable_index
+=
2
for
count
in
x
range
(
len
(
values_list
))
:
for
count
in
range
(
len
(
values_list
))
:
self
.
__config_file_data_list
.
insert
(
last_variable_index
+
count
,
"
%
s =
%
s"
%
(
variable_name
,
str
(
values_list
[
count
])))
def
value
(
self
,
section_name
,
variable_name
)
:
...
...
settingsd/validators/__init__.py
View file @
de464448
...
...
@@ -4,5 +4,5 @@
__all__
=
[
"common"
,
"network"
,
"os"
]
from
common
import
ValidatorError
from
.
common
import
ValidatorError
settingsd/validators/network.py
View file @
de464448
# -*- coding: utf-8 -*-
from
common
import
ValidatorError
from
.
common
import
ValidatorError
##### Public methods #####
...
...
@@ -12,7 +12,7 @@ def validIpv4Address(arg) :
if
len
(
octets_list
)
!=
4
:
raise
ValidatorError
(
"Argument
\"
%
s
\"
is not valid IPv4 address"
%
(
arg
))
for
count
in
x
range
(
4
)
:
for
count
in
range
(
4
)
:
try
:
octets_list
[
count
]
=
int
(
octets_list
[
count
])
if
not
0
<=
octets_list
[
count
]
<=
255
:
...
...
@@ -36,14 +36,14 @@ def validIpv4Netmask(arg) :
octets_list
=
[
0
]
*
4
one_count
=
arg
for
count
in
x
range
(
4
)
:
for
count
in
range
(
4
)
:
octet_one_count
=
8
while
one_count
and
octet_one_count
:
octets_list
[
count
]
|=
128
>>
8
-
octet_one_count
one_count
-=
1
octet_one_count
-=
1
elif
len
(
octets_list
)
==
4
:
for
count
in
x
range
(
4
)
:
for
count
in
range
(
4
)
:
try
:
octets_list
[
count
]
=
int
(
octets_list
[
count
])
if
not
0
<=
octets_list
[
count
]
<=
255
:
...
...
@@ -62,7 +62,7 @@ def validMacAddress(arg) :
if
len
(
octets_list
)
!=
6
:
raise
ValidatorError
(
"Argument
\"
%
s
\"
is not valid MAC address"
%
(
arg
))
for
count
in
x
range
(
6
)
:
for
count
in
range
(
6
)
:
try
:
octets_list
[
count
]
=
int
(
octets_list
[
count
],
16
)
if
not
0
<=
octets_list
[
count
]
<=
255
:
...
...
settingsd/validators/os.py
View file @
de464448
...
...
@@ -3,7 +3,7 @@
import
re
from
common
import
ValidatorError
from
.
common
import
ValidatorError
##### Public methods #####
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment