SlideShare ist ein Scribd-Unternehmen logo
1 von 20
Downloaden Sie, um offline zu lesen
PySmbC:
C Modules are Easy
EuroPython 2012, 6th July - Firenze




          Babel Srl P.zza S. Benedetto da Norcia, 33 0040, Pomezia (RM) – www.babel.it

                            Roberto Polli - roberto.polli@babel.it
What? Who? Why?
A success story about using GitHub and Nose testing framework.

Roberto Polli - Community Manager @ Babel.it. Loves writing in C,
Java and Python. Red Hat Certified Engineer.

Fabio Isgrò – System Engineer @ Babel.it. Linux and Samba
expert.

Babel – Proud sponsor of this talk ;) Delivers large mail
infrastructures based on Open Source software for Italian ISP and
PA. Contributes to various FLOSS.



                       Roberto Polli - roberto.polli@babel.it
Agenda – 1 - prerequisites
 People enjoy FLOSS but...why is afraid of contributing?

+ GitHub: track forks, fast merges

+ Python: C Extension are easy

+ Nose Test: simplify testing process


    = Don't have to be a Guru to support FLOSS!




                      Roberto Polli - roberto.polli@babel.it
Agenda – 2 - contributing
Samba and samba-client library.

Clone a project, get in touch with the maintainer.

Write test first.

Wrapping get_xattr and set_xattr, manage ACL.


      Don't need to know SMB to extend PySmbC




                        Roberto Polli - roberto.polli@babel.it
GitHub – social coding
FLOSS Coding is a relational stuff.

Coding 1.0: send .patch to a mailing list

Coding 2.0: fork me on GitHub
https://github.com/ioggstream/pysmbc



               Did you say...fork?


                   Roberto Polli - roberto.polli@babel.it
GitHub – social coding
Forking is the nightmare of every
floss maintainer.

Sparse writes, increasing merge
efforts, lost changes.

GitHub, like the I/O Scheduler,
helps to merge writes!
●
  Tracks forks;
●
  Push changes to master.




                        Roberto Polli - roberto.polli@babel.it
GitHub – social coding
Patch and commit to your repository
●
 don't lose your changes;
●
 track your own history.
Push your changes to my repo
●
 no more for .patch;
●
 I get the change history.
Discuss for approval
●
 Github portal supports code annotations.
Merge my changes
●
 use git to merge from a remote repository!




                       Roberto Polli - roberto.polli@babel.it
Enter PySmbC - Extensions
Python wrapper around libsmbclient: run C code from python
– enjoy a stable C library;
– just manage input, output and errors:
– usually faster than a pure python implementation.

 rpolli$ ipython
 ln [1]: import smbc                                      smbc.so
 ln [2]: print smbc.XATTR_ACL
 system.nt_sec_desc.acl
                                                      libsmbclient.so.0
 ln [3]:




                       Roberto Polli - roberto.polli@babel.it
Example - Wrapping factorial() - 1
The wrapping function my_factorial():
                                                                     // Python C Extension




                                                       wrapperfy.c
●
 Parses and validates the input;                                     // uses factorial from fact.c
●
 Calls the wrapped function();                                       #include <fact.h>

                                                                     // returns a python object!
●
 Returns a python object.                                            PyObject *my_factorial(...) {
                                                                          ...
                                                                          ret = factorial(n);
                                                                           ...
                                                                         return PyLong_asLong(ret);
A given structure maps python methods to                             }

C functions.

gcc wrapperfy.c -o _wrapper.so -shared
                                                            // Maps _wrapper.factorial
                      # python script                       // to my_factorial
                      from _wrapper import factorial
                                                            PyMethodDef BabelMethods[] = {
Now we can invoke a                                           {"factorial", my_factorial, ... },
                      print factorial(4)                      {NULL, NULL, 0, NULL} /*Sentinel*/
wrapped function!                                           };




                       Roberto Polli - roberto.polli@babel.it
Example - Wrapping factorial() - 2
Parsing and validating Input and                   // returns a python object!
                                                   PyObject *my_factorial(..., *args) {
Output is crucial. We don't want python              // NULL indicates an error
                                                     if (!PyArg_ParseTuple(args, "i", &n))
to SEGFAULT!                                           return NULL;
                                                     // n! > max(long long int)
                                                     if (n>21) {
                                                       ...
                                                       PyErr_SetString(FactError, 
Create new exceptions in the                             “Bad value”);
                                                       return NULL;
initialization function.                             }
                                                     ... 
                                                     return PyLong_asLong(ret);
                                                   }

Throw exceptions in the function:                  PyObject *FactError;
●
 setting PyErr;                                    // in extension initialization...
                                                   ...
                                                   init_wrapper(void) {
●
 returning NULL.                                     ...
                                                     // define an exception
                                                     FactError = 
                                                       PyErr_NewException("_wrapper.error", 
                                                         NULL, NULL);
                                                     ...
                                                   }



                       Roberto Polli - roberto.polli@babel.it
Example - Wrapping factorial() - 3
                                                       // Python C Extension
C Extension components:                                #include <Python.h>

●
 wrapping functions;                                   // exceptions
                                                       PyObject *FactError;
                                                       PyObject *FiboError;
●
 method/function map;                                  // functions
●
 exceptions;                                           PyObject *my_factorial(...);
                                                       PyObject *my_fibonacci(...);
●
 initialization function.                              // Function/Method Maps 

                                                       PyMethodDef BabelMethods[] = {
                                                         {"factorial",my_factorial,... },
Functions and Exception should be static                 {"fibonacci",my_fibonacci,... },
                                                         {NULL, NULL, 0, NULL} /*Sentinel*/
                                                       };

                                                      PyMODINIT_FUNC

 You have to track memory usage!                      init_wrapper(void)
                                                      {
                                                        PyObject *m;
                                                        m = Py_InitModule("_wrapper",
                                                              BabelMethods);
                                                        // … Allocate Exceptions
                                                        FactError = PyErr_NewException(...)
                                                        FiboError = PyErr_NewException(...)
                                                      }



                       Roberto Polli - roberto.polli@babel.it
Enters PySmbC - Modules
Python C extensions
may enjoy both C and
Python code.

Wrap the C extension in
a Python module.

Extend the module with
python classes.

$PYTHONPATH/
  wrapper/
    __init__.py           In [1]: import wrapper
                          In [2]: assert wrapper.helpers
    _wrapper.so           In [3]: wrapper.helpers.is_integer(10)
    helpers.py

                           Roberto Polli - roberto.polli@babel.it
Nose – let's contribute - 1
Before adding features to PySmbC we checked the project
status
 # git clone https://github.com/ioggstream/pysmbc .
 # vim tests/settings.py # set samba credential
 # nosetests test/

NoseTest - a python script that auto-discovers and run test
cases. Wraps python-unittest.

Add new features only after successful tests. Verify your
environment (eg. Samba credentials, directory acls )



                       Roberto Polli - roberto.polli@babel.it
Nose – let's contribute - 2
On successful tests, we can start developing

Follow the Git way: create a separate branch. We'll merge
it on success
 # git checkout -b ioggstream_setxattr

Write the tests before writing the code. You'll be more focused on
your targets

            With nosetest it's simpler than ever!




                       Roberto Polli - roberto.polli@babel.it
Nose – is like UnitTest
UnitTest                                     Nose
from unittest import TestCase, main          import nose


class MyTest(UnitTest):                      class MyTest:
  def setUp(self):                               def setup(self):
    print”setup every”                             print ”setup”
  def tearDown(self):                            def teardown(self):
    print “teardown every”                         print “teardown”
  def test_do(self):                             def test_do(self):
    print “do 1”                                   print “do 1”


if __name__== “__main__”:                    # nose script will auto-discover
    main()                                   #   this script named test_script.py




                             Roberto Polli - roberto.polli@babel.it
Nose – is simpler than UnitTest
Nose: simple test                         Nose: annotations
# don't need to import nose               from nose import SkipTest,with_setup
# or define a class
                                          def pre(): print “setup”
def setup():                              def post(): print “teardown”
  print”setup once for all tests”
def teardown():                           @with_setup(pre,post)
  print “teardown once for all test”      def test_do():
                                             print “do 1”

def test_do():
                                          @SkipTest
  print “do 1”
                                          def test_dont():
def test_fail():
                                              Print “not done yet”
  assert False




                          Roberto Polli - roberto.polli@babel.it
Nose – Invocation
You can run your all tests in a given directory
 # nosetests ./path/
Or just one file
 # nosetests ./path/test_sample.py
Or even a single test method
 # nosetests ./path/test_sample.py:test_do1
Or suite, eventually setting the working directory
 ex1# nosetests ./path/test_class.py:TestOne
 ex2# nosetests -w ./path test_class:TestOne
For a verbose output just use:
 #nosetests -sv [args]


                     Roberto Polli - roberto.polli@babel.it
PySmbC – add getxattr
                                                             # from test_context.py
Nose ensures that we're not going to                         def test_xattr_constants():
break anything.                                                '''reuse variable defined
                                                               in smbclient.h'''
                                                               assert smbc.XATTR_ACL
Start writing tests, not coding                                assert smbc.XATTR_OWNER
                                                               assert smbc.XATTR_GROUP
functionalities.
                                                             def test_xattr_get():
You can @SkipTest until new functions are ready.               '''test xattr with all
                                                                possible values'''
                                                               . . .
Play with the wrapped functions.                               for xa in valid_xatts:
                                                                 assert ctx.getxattr(url, xa)

                                                             def test_xattr_get_error():
Start with the simpler one: getxattr()                         '''xattr_get should
●embed C constants into python;                                 recognize bad values'''
                                                               . . .
●test good values;
                                                               for xa in invalid_xatts:
●check behavior with bad values.
                                                                 try:
                                                                   ctx.getxattr(url, xa)
                                                                   assert False
                                                                 except RuntimeError as e:
Code until tests are successful.                                   . . . #get errno
                                                                   assert errno == EINVAL


                             Roberto Polli - roberto.polli@babel.it
PySmbC – add setxattr and futures
Helper methods for parsing and                             # from test_context.py

creating ACL                                               def test_xattr_set():
attrs_new = u'REVISION:1'                                   . . .
                                                             ctx.setxattr(url, a_name,
 + ',OWNER:RPOLLIbabel' 
                                                               attrs_new, REPLACE)
 + ',GROUP:Unix Groupbabel'                               attrs_1 = ctx.getxattr(url,
 + ',ACL:RPOLLIbabel:0/0/0x001e01ff'                    a_name)
 + ',ACL:Unix Groupbabel:0/0/0x00120089'                  assert attrs_1 == attrs_new

 + ',ACL:Unix Groupgames:0/0/0x001e01ff'                def test_xattr_set_error():
 + ',ACL:Everyone:0/0/0x00120089'                          '''setxattr should
                                                              recognize bad values'''
                                                             . . .
Shift from smbc.so to smbc module:                           for xa in invalid_xatts:
                                                               try:
●
  smbc/_smbc.so                                                  ctx.setxattr(url, a_name,
                                                                    xa, REPLACE)
●
  smbc/__init__.py                                               assert False
●
  smbc/helper.py                                               except RuntimeError as e:
                                                                 . . . #get errno
                                                                 assert errno == EINVAL
                                                               except TypeError
                                                                 pass

                              Roberto Polli - roberto.polli@babel.it
PySmbC
https://github.com/ioggstream/pysmbc
http://pypi.python.org/pypi/pysmbc/
http://www.samba.org


Babel
http://www.babel.it
http://vaunaspada.babel.it/blog




                Thank You!
         roberto.polli@babel.it

                Roberto Polli - roberto.polli@babel.it

Weitere ähnliche Inhalte

Mehr von Babel

Mehr von Babel (20)

Sophos Complete Security: arte e scienza della sicurezza
Sophos Complete Security: arte e scienza della sicurezzaSophos Complete Security: arte e scienza della sicurezza
Sophos Complete Security: arte e scienza della sicurezza
 
L’innovazione a difesa della tradizione: il caso dell’Archivio Storico della ...
L’innovazione a difesa della tradizione: il caso dell’Archivio Storico della ...L’innovazione a difesa della tradizione: il caso dell’Archivio Storico della ...
L’innovazione a difesa della tradizione: il caso dell’Archivio Storico della ...
 
L’innovazione a difesa della tradizione: il caso dell’Archivio Storico della ...
L’innovazione a difesa della tradizione: il caso dell’Archivio Storico della ...L’innovazione a difesa della tradizione: il caso dell’Archivio Storico della ...
L’innovazione a difesa della tradizione: il caso dell’Archivio Storico della ...
 
Intercettazioni: guida alle nuove norme per i provider
Intercettazioni: guida alle nuove norme per i providerIntercettazioni: guida alle nuove norme per i provider
Intercettazioni: guida alle nuove norme per i provider
 
Dalla virtualizzazione al private cloud: Il Patronato INCA rinnova la fiducia...
Dalla virtualizzazione al private cloud: Il Patronato INCA rinnova la fiducia...Dalla virtualizzazione al private cloud: Il Patronato INCA rinnova la fiducia...
Dalla virtualizzazione al private cloud: Il Patronato INCA rinnova la fiducia...
 
Will iPython replace Bash?
Will iPython replace Bash?Will iPython replace Bash?
Will iPython replace Bash?
 
La gestione integrata della sicurezza in ANSA: dal firewalling all'UTM
La gestione integrata della sicurezza in ANSA: dal firewalling all'UTMLa gestione integrata della sicurezza in ANSA: dal firewalling all'UTM
La gestione integrata della sicurezza in ANSA: dal firewalling all'UTM
 
Installare i server via rete con Cobbler
Installare i server via rete con CobblerInstallare i server via rete con Cobbler
Installare i server via rete con Cobbler
 
Shell Control Box - Il Gusto della Sicurezza
Shell Control Box - Il Gusto della SicurezzaShell Control Box - Il Gusto della Sicurezza
Shell Control Box - Il Gusto della Sicurezza
 
Tracciamento delle attività di amministrazione mediante i BalaBit Shell Contr...
Tracciamento delle attività di amministrazione mediante i BalaBit Shell Contr...Tracciamento delle attività di amministrazione mediante i BalaBit Shell Contr...
Tracciamento delle attività di amministrazione mediante i BalaBit Shell Contr...
 
La Desktop Virtualization
La Desktop VirtualizationLa Desktop Virtualization
La Desktop Virtualization
 
Crittografia e integrazione dei sistemi con Python
Crittografia e integrazione dei sistemi con PythonCrittografia e integrazione dei sistemi con Python
Crittografia e integrazione dei sistemi con Python
 
Intercettazioni e posta elettronica: le misure di sicurezza per i gestori
Intercettazioni e posta elettronica: le misure di sicurezza per i gestoriIntercettazioni e posta elettronica: le misure di sicurezza per i gestori
Intercettazioni e posta elettronica: le misure di sicurezza per i gestori
 
Babel presenta: Opsview
Babel presenta: OpsviewBabel presenta: Opsview
Babel presenta: Opsview
 
Monitoraggio di infrastrutture IT mediante Opsview Enteprise V4
Monitoraggio di infrastrutture IT mediante Opsview Enteprise V4Monitoraggio di infrastrutture IT mediante Opsview Enteprise V4
Monitoraggio di infrastrutture IT mediante Opsview Enteprise V4
 
OpenVAS, lo strumento open source per il vulnerability assessment
OpenVAS, lo strumento open source per il vulnerability assessmentOpenVAS, lo strumento open source per il vulnerability assessment
OpenVAS, lo strumento open source per il vulnerability assessment
 
Testing with MySQL embedded
Testing with MySQL embeddedTesting with MySQL embedded
Testing with MySQL embedded
 
Cross compiler per uso domestico
Cross compiler per uso domesticoCross compiler per uso domestico
Cross compiler per uso domestico
 
Sicurezza flessibile con SELinux: architettura e configurazione
Sicurezza flessibile con SELinux: architettura e configurazioneSicurezza flessibile con SELinux: architettura e configurazione
Sicurezza flessibile con SELinux: architettura e configurazione
 
Ridirezionamento di I/O con Bash: un breve approfondimento
Ridirezionamento di I/O con Bash: un breve approfondimentoRidirezionamento di I/O con Bash: un breve approfondimento
Ridirezionamento di I/O con Bash: un breve approfondimento
 

Kürzlich hochgeladen

Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Safe Software
 
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
?#DUbAI#??##{{(☎️+971_581248768%)**%*]'#abortion pills for sale in dubai@
 

Kürzlich hochgeladen (20)

AWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of TerraformAWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of Terraform
 
Elevate Developer Efficiency & build GenAI Application with Amazon Q​
Elevate Developer Efficiency & build GenAI Application with Amazon Q​Elevate Developer Efficiency & build GenAI Application with Amazon Q​
Elevate Developer Efficiency & build GenAI Application with Amazon Q​
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
 
CNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In PakistanCNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In Pakistan
 
Corporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptxCorporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptx
 
DEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 AmsterdamDEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
 
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
 
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
 
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost SavingRepurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
 
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a Fresher
 
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
 
MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024
 
WSO2's API Vision: Unifying Control, Empowering Developers
WSO2's API Vision: Unifying Control, Empowering DevelopersWSO2's API Vision: Unifying Control, Empowering Developers
WSO2's API Vision: Unifying Control, Empowering Developers
 
Platformless Horizons for Digital Adaptability
Platformless Horizons for Digital AdaptabilityPlatformless Horizons for Digital Adaptability
Platformless Horizons for Digital Adaptability
 
Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...
Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...
Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
 
DBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor PresentationDBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor Presentation
 
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, AdobeApidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
 
MS Copilot expands with MS Graph connectors
MS Copilot expands with MS Graph connectorsMS Copilot expands with MS Graph connectors
MS Copilot expands with MS Graph connectors
 

Ottimizzare il ciclo di sviluppo e test mediante Python, Nose e GitHub

  • 1. PySmbC: C Modules are Easy EuroPython 2012, 6th July - Firenze Babel Srl P.zza S. Benedetto da Norcia, 33 0040, Pomezia (RM) – www.babel.it Roberto Polli - roberto.polli@babel.it
  • 2. What? Who? Why? A success story about using GitHub and Nose testing framework. Roberto Polli - Community Manager @ Babel.it. Loves writing in C, Java and Python. Red Hat Certified Engineer. Fabio Isgrò – System Engineer @ Babel.it. Linux and Samba expert. Babel – Proud sponsor of this talk ;) Delivers large mail infrastructures based on Open Source software for Italian ISP and PA. Contributes to various FLOSS. Roberto Polli - roberto.polli@babel.it
  • 3. Agenda – 1 - prerequisites People enjoy FLOSS but...why is afraid of contributing? + GitHub: track forks, fast merges + Python: C Extension are easy + Nose Test: simplify testing process = Don't have to be a Guru to support FLOSS! Roberto Polli - roberto.polli@babel.it
  • 4. Agenda – 2 - contributing Samba and samba-client library. Clone a project, get in touch with the maintainer. Write test first. Wrapping get_xattr and set_xattr, manage ACL. Don't need to know SMB to extend PySmbC Roberto Polli - roberto.polli@babel.it
  • 5. GitHub – social coding FLOSS Coding is a relational stuff. Coding 1.0: send .patch to a mailing list Coding 2.0: fork me on GitHub https://github.com/ioggstream/pysmbc Did you say...fork? Roberto Polli - roberto.polli@babel.it
  • 6. GitHub – social coding Forking is the nightmare of every floss maintainer. Sparse writes, increasing merge efforts, lost changes. GitHub, like the I/O Scheduler, helps to merge writes! ● Tracks forks; ● Push changes to master. Roberto Polli - roberto.polli@babel.it
  • 7. GitHub – social coding Patch and commit to your repository ● don't lose your changes; ● track your own history. Push your changes to my repo ● no more for .patch; ● I get the change history. Discuss for approval ● Github portal supports code annotations. Merge my changes ● use git to merge from a remote repository! Roberto Polli - roberto.polli@babel.it
  • 8. Enter PySmbC - Extensions Python wrapper around libsmbclient: run C code from python – enjoy a stable C library; – just manage input, output and errors: – usually faster than a pure python implementation. rpolli$ ipython ln [1]: import smbc smbc.so ln [2]: print smbc.XATTR_ACL system.nt_sec_desc.acl libsmbclient.so.0 ln [3]: Roberto Polli - roberto.polli@babel.it
  • 9. Example - Wrapping factorial() - 1 The wrapping function my_factorial(): // Python C Extension wrapperfy.c ● Parses and validates the input; // uses factorial from fact.c ● Calls the wrapped function(); #include <fact.h> // returns a python object! ● Returns a python object. PyObject *my_factorial(...) { ... ret = factorial(n); ... return PyLong_asLong(ret); A given structure maps python methods to } C functions. gcc wrapperfy.c -o _wrapper.so -shared // Maps _wrapper.factorial # python script // to my_factorial from _wrapper import factorial PyMethodDef BabelMethods[] = { Now we can invoke a {"factorial", my_factorial, ... }, print factorial(4) {NULL, NULL, 0, NULL} /*Sentinel*/ wrapped function! }; Roberto Polli - roberto.polli@babel.it
  • 10. Example - Wrapping factorial() - 2 Parsing and validating Input and // returns a python object! PyObject *my_factorial(..., *args) { Output is crucial. We don't want python   // NULL indicates an error   if (!PyArg_ParseTuple(args, "i", &n)) to SEGFAULT!     return NULL;   // n! > max(long long int)   if (n>21) {     ...     PyErr_SetString(FactError,  Create new exceptions in the       “Bad value”);     return NULL; initialization function.   }   ...    return PyLong_asLong(ret); } Throw exceptions in the function: PyObject *FactError; ● setting PyErr; // in extension initialization... ... init_wrapper(void) { ● returning NULL.   ...   // define an exception   FactError =      PyErr_NewException("_wrapper.error",        NULL, NULL);   ... } Roberto Polli - roberto.polli@babel.it
  • 11. Example - Wrapping factorial() - 3 // Python C Extension C Extension components: #include <Python.h> ● wrapping functions; // exceptions PyObject *FactError; PyObject *FiboError; ● method/function map; // functions ● exceptions; PyObject *my_factorial(...); PyObject *my_fibonacci(...); ● initialization function. // Function/Method Maps  PyMethodDef BabelMethods[] = {   {"factorial",my_factorial,... }, Functions and Exception should be static   {"fibonacci",my_fibonacci,... },   {NULL, NULL, 0, NULL} /*Sentinel*/ }; PyMODINIT_FUNC You have to track memory usage! init_wrapper(void) { PyObject *m; m = Py_InitModule("_wrapper", BabelMethods); // … Allocate Exceptions FactError = PyErr_NewException(...) FiboError = PyErr_NewException(...) } Roberto Polli - roberto.polli@babel.it
  • 12. Enters PySmbC - Modules Python C extensions may enjoy both C and Python code. Wrap the C extension in a Python module. Extend the module with python classes. $PYTHONPATH/ wrapper/ __init__.py In [1]: import wrapper In [2]: assert wrapper.helpers _wrapper.so In [3]: wrapper.helpers.is_integer(10) helpers.py Roberto Polli - roberto.polli@babel.it
  • 13. Nose – let's contribute - 1 Before adding features to PySmbC we checked the project status # git clone https://github.com/ioggstream/pysmbc . # vim tests/settings.py # set samba credential # nosetests test/ NoseTest - a python script that auto-discovers and run test cases. Wraps python-unittest. Add new features only after successful tests. Verify your environment (eg. Samba credentials, directory acls ) Roberto Polli - roberto.polli@babel.it
  • 14. Nose – let's contribute - 2 On successful tests, we can start developing Follow the Git way: create a separate branch. We'll merge it on success # git checkout -b ioggstream_setxattr Write the tests before writing the code. You'll be more focused on your targets With nosetest it's simpler than ever! Roberto Polli - roberto.polli@babel.it
  • 15. Nose – is like UnitTest UnitTest Nose from unittest import TestCase, main import nose class MyTest(UnitTest): class MyTest: def setUp(self): def setup(self): print”setup every” print ”setup” def tearDown(self): def teardown(self): print “teardown every” print “teardown” def test_do(self): def test_do(self): print “do 1” print “do 1” if __name__== “__main__”: # nose script will auto-discover main() # this script named test_script.py Roberto Polli - roberto.polli@babel.it
  • 16. Nose – is simpler than UnitTest Nose: simple test Nose: annotations # don't need to import nose from nose import SkipTest,with_setup # or define a class def pre(): print “setup” def setup(): def post(): print “teardown” print”setup once for all tests” def teardown(): @with_setup(pre,post) print “teardown once for all test” def test_do(): print “do 1” def test_do(): @SkipTest print “do 1” def test_dont(): def test_fail(): Print “not done yet” assert False Roberto Polli - roberto.polli@babel.it
  • 17. Nose – Invocation You can run your all tests in a given directory # nosetests ./path/ Or just one file # nosetests ./path/test_sample.py Or even a single test method # nosetests ./path/test_sample.py:test_do1 Or suite, eventually setting the working directory ex1# nosetests ./path/test_class.py:TestOne ex2# nosetests -w ./path test_class:TestOne For a verbose output just use: #nosetests -sv [args] Roberto Polli - roberto.polli@babel.it
  • 18. PySmbC – add getxattr # from test_context.py Nose ensures that we're not going to def test_xattr_constants(): break anything. '''reuse variable defined in smbclient.h''' assert smbc.XATTR_ACL Start writing tests, not coding assert smbc.XATTR_OWNER assert smbc.XATTR_GROUP functionalities. def test_xattr_get(): You can @SkipTest until new functions are ready. '''test xattr with all possible values''' . . . Play with the wrapped functions. for xa in valid_xatts: assert ctx.getxattr(url, xa) def test_xattr_get_error(): Start with the simpler one: getxattr() '''xattr_get should ●embed C constants into python; recognize bad values''' . . . ●test good values; for xa in invalid_xatts: ●check behavior with bad values. try: ctx.getxattr(url, xa) assert False except RuntimeError as e: Code until tests are successful. . . . #get errno assert errno == EINVAL Roberto Polli - roberto.polli@babel.it
  • 19. PySmbC – add setxattr and futures Helper methods for parsing and # from test_context.py creating ACL def test_xattr_set(): attrs_new = u'REVISION:1' . . . ctx.setxattr(url, a_name, + ',OWNER:RPOLLIbabel' attrs_new, REPLACE) + ',GROUP:Unix Groupbabel' attrs_1 = ctx.getxattr(url, + ',ACL:RPOLLIbabel:0/0/0x001e01ff' a_name) + ',ACL:Unix Groupbabel:0/0/0x00120089' assert attrs_1 == attrs_new + ',ACL:Unix Groupgames:0/0/0x001e01ff' def test_xattr_set_error(): + ',ACL:Everyone:0/0/0x00120089' '''setxattr should recognize bad values''' . . . Shift from smbc.so to smbc module: for xa in invalid_xatts: try: ● smbc/_smbc.so ctx.setxattr(url, a_name, xa, REPLACE) ● smbc/__init__.py assert False ● smbc/helper.py except RuntimeError as e: . . . #get errno assert errno == EINVAL except TypeError pass Roberto Polli - roberto.polli@babel.it